Xm and more (#17)

* Added partial XM support
Added POT support to Pokey
Modifed Pokey and TIA Buffers
Fixed issue where pokey counter was not being reset
Added temporary hack to get Pac320 to work (may cause issues)

* Added Pokey @450 support
Added Support for carts about 144k
Improved cart detection (via header and by size)
Fixed issue occurring when Kangaroo and Holey were enabled (caused
backgroud to be displayed causing large black squares)

* Added ability to edit cartridge DB in UI
Added disable bios, left/right switch, swap buttons, pokey@450, and xm
to cartridge database.
Fixed Pokey pops that were occurring
Removed WSYNC, cycle stealing, and swap buttons from global settings

* Fixed bug with cart db UI and dual analog

* Added XM to save states

* Defaults to latest save state when loading cart

* Minor menu fix (able to select spacer)

* Reorganized advanced menu

* Added whether cart was loaded from db in debug

* Temporarily disable BIOS support
Will enable once issue is resolved

* Reduced TIA volume slightly

* Fixed controller for crossbow and alien brigade

* Added Bentley Bear's Crystal Quest to DB

* Bank switching fixes, new cart type
Fixed 64k cart bank switching when specifying out of range bank
Added new cartridge mode "Standard RAM". 64k or less w/ RAM at $4000
Removed global high score cart setting
Added per-cartridge setting for HSC (default to header value)

* Updates to prosystem database
Cartridge size uses file size (vs. header)
Default controllers to joysticks
Fix database load issue (sometimes read into next entry)
Added default cart title (when not in header or DB)
Added another default screen size
Fixed vsync issue (caused stutter, mostly on PAL titles)

* Many homebrew additions to cart database
Fixed issue where some IM hacks were not loading
Updated db editor to always write out pokey450 and XM settings

* More cart database entries

* Updated readme files and images for 0.5 release

* Updated readme

* Updated release date
This commit is contained in:
Chris Smith 2020-03-24 19:30:12 -07:00 committed by GitHub
parent 66962fb345
commit 3e4adaee79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 3595 additions and 411 deletions

View file

@ -45,8 +45,8 @@ CFLAGS = \
-g -O1 -Wall $(MACHDEP) $(INCLUDE) \
-DNOCRYPT -DWII -DBIG_ENDIAN -DWII_BIN2O \
-Wno-format-truncation \
-Wno-narrowing
-Wno-narrowing
#-DWII_NETTRACE
#-DLOWTRACE -DDEBUG
CXXFLAGS = $(CFLAGS)
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
@ -91,6 +91,7 @@ CPPFILES := \
Cartridge.cpp \
Common.cpp \
Database.cpp \
ExpansionModule.cpp \
Hash.cpp \
Logger.cpp \
Maria.cpp \
@ -106,6 +107,7 @@ CPPFILES := \
Tia.cpp \
wii_atari.cpp \
wii_atari_config.cpp \
wii_atari_db.cpp \
wii_atari_emulation.cpp \
wii_atari_menu.cpp \
wii_atari_sdl.cpp \

106
README.md
View file

@ -5,15 +5,16 @@
Ported by raz0red
Wii7800 is a Nintendo Wii port of the ProSystem emulator developed by Greg Stanton.
Wii7800 is a port of the ProSystem emulator developed by Greg Stanton.
Additional changes developed by Ludovic Jacomme aka Zx-81 (PSP port), Leonis,
and gdement. Portions of the Pokey code were adapted from the MAME
implementation.
[https://gstanton.github.io/ProSystem1_3/]
| ![](https://wiibrew.org/w/images/thumb/1/16/7800-pole.gif/189px-7800-pole.gif) | ![](https://wiibrew.org/w/images/thumb/a/a5/7800-commando.gif/189px-7800-commando.gif) | ![](https://wiibrew.org/w/images/thumb/d/dd/7800-ninja.gif/189px-7800-ninja.gif) |
|---|---|---|
_Wii7800 0.5 + Atari 7800 Homebrew Video_
<a href='http://www.youtube.com/watch?feature=player_embedded&v=Qq7qgz8fVgs' target='_blank'><img src='http://img.youtube.com/vi/Qq7qgz8fVgs/0.jpg' width='425' height=344 /></a>
## Current status
@ -29,26 +30,37 @@ please visit the [Wii7800 page](http://www.wiibrew.org/wiki/Wii7800) on WiiBrew:
## Installation
To install Wii7800, simply extract the zip file directly to your SD card
(retain the hierarchical structure exactly).
Cartridge images must be placed in the roms directory (/wii7800/roms).
(Zip files are supported)
Wii7800 does support loading of the Atari 7800 BIOS, although it isn't
necessary. If you wish to use the BIOS, simply place the NTSC and PAL BIOS
files in the (/wii7800) directory. The NTSC file must be named, "7800.rom",
while the PAL file must be named, "7800pal.rom".
or USB device (retain the hierarchical structure exactly).
## Lightgun Accuracy, etc.
The crosshair for the Wii7800 emulator is not perfect. For example you may be
pointing at something and your shot may register to the right or left. This is
due to the way the 7800 handles hit detection for lightgun games. It only
checks for a hit every 7 CPU cycles. There are 330 cycles for the visible
portion of each frame. Thus, there are only ~47 hit points for each scanline.
So, the crosshair at best gets you in approximately the right area, and if you
miss you need to adjust based on where the shot shows up on the screen
(exactly how you do it when there is no crosshair).
The crosshair for the Wii7800 emulator is not perfect. For example, you
may be pointing at something and your shot may register slightly to the
right or left.
## Cartridge Database
Wii7800 ships with a database that contains recommended settings for the
majority of commercial and a limited number of homebrew cartridges. These
settings cover control settings, difficulty switch settings, and
cartridge-related settings (cartridge type, Pokey support, XM support,
high score cart support, etc.).
To view/edit the settings applied for a particular cartridge perform the
following steps:
* Load the cartridge (via the "Load cartridge" menu item)
* Return to the Wii7800 menu
* Select the "Cartridge-specific settings" menu item
* View/edit the settings for the cartridge
Some settings will not be applied until the settings are saved and the
cartridge is reloaded. When one of these settings is modified, a message
will be displayed indicating that this particular setting requires the
cartridge to be reloaded (and the settings saved prior to loading).
Other settings, such as difficulty switch and control settings may not
be applied until the cartridge is reset (or reloaded).
## Cartridge/ROM Compatibility
@ -152,6 +164,17 @@ This page contains a list of compatible ROMs by "hash code".
1 : Left difficulty (if enabled)
2 : Right difficulty (if enabled)
Home : Display Wii7800 menu (see above)
## SMB (Network support)
Wii7800 allows for loading ROMs over the network via SMB. To enable SMB
support, you must edit the "wii7800.conf" file located in the "/wii7800"
directory and provide values for the following:
* share_ip : IP address of the computer to connect to.
* share_name : Name of the share on the computer.
* share_user : Name of the user to connect as
* share_pass : Password for the user
## Wii7800 crashes, code dumps, etc.
@ -174,6 +197,48 @@ the following locations:
## Change log
### 03/24/20 (0.5)
- Partial Expansion Module (XM) support
- XRAM
- XPokey (limited to single Pokey)
- Added support for cartridges with sizes greater than 144k
- Additional bank switching modes and cartridge types
- Multiple bank switching fixes
- Reworked cartridge header detection
- Now properly detects bank switching, RAM, etc.
- Detects Expansion Module (XM)
- Detects High score cartridge
- Detects Pokey at $0450
- Cartridge database
- Added ability to edit cartridge database settings via menu
- Added several new cartridge properties
- Pokey at $0450
- Default difficulty switch settings
- Expansion Module (XM) enabled/disabled
- High score cartridge enabled/disabled
- Database content
- Fixed incorrect controller settings for Sirius, Crossbow,
and Alien Brigade
- Added many homebrew cartridges
- Display enhancements
- Double strike (240p)
- GX+VI mode
- 16:9 correction
- Full widescreen support
- Ability to enable/disable bilinear filter (GX mode)
- Color trap filter
- Multiple default screen sizes
- Hierarchical file navigation support
- USB Support
- SMB (Network support) for loading ROMs
- Multi-save slot support
- Reworked menu system (cartridge-specific settings, etc.)
- Support for launching via WiiFlow (and returning)
- Fixed VSYNC issue which caused initial stutter on PAL games
- Fixed issue occurring when Kangaroo and Holey were enabled (caused
background to be displayed, resulting in large black squares)
- Several audio improvements (eliminated majority of TIA and Pokey pops)
### 11/16/19 (0.4)
- Reworked audio integration (resolves audio clipping and popping)
- Refactored project layout. Now includes third party libraries, which
@ -239,4 +304,3 @@ the following locations:
- Controls support for Wiimote/Nunchuk/Classic/Gamecube controllers
- Analog controls support
- Dual analog support for Gamecube/Classic controllers (Robotron)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View file

@ -1,5 +1,5 @@
--------------------------------------------
Wii7800 v0.5-SNAPSHOT release README
Wii7800 v0.5 release README
--------------------------------------------
Ported by raz0red [github.com/raz0red]
@ -37,14 +37,6 @@ Installation
To install Wii7800, simply extract the zip file directly to your SD card
or USB device (retain the hierarchical structure exactly).
Cartridge images must be placed in the roms directory (/wii7800/roms).
(Zip files are supported)
Wii7800 does support loading of the Atari 7800 BIOS, although it isn't
necessary. If you wish to use the BIOS, simply place the NTSC and PAL BIOS
files in the (/wii7800) directory. The NTSC file must be named, "7800.rom",
while the PAL file must be named, "7800pal.rom".
--------------------------------------------
Lightgun Accuracy, etc.
--------------------------------------------
@ -53,6 +45,32 @@ The crosshair for the Wii7800 emulator is not perfect. For example, you
may be pointing at something and your shot may register slightly to the
right or left.
--------------------------------------------
Cartridge Database
--------------------------------------------
Wii7800 ships with a database that contains recommended settings for the
majority of commercial and a limited number of homebrew cartridges. These
settings cover control settings, difficulty switch settings, and
cartridge-related settings (cartridge type, Pokey support, XM support,
high score cart support, etc.).
To view/edit the settings applied for a particular cartridge perform the
following steps:
* Load the cartridge (via the "Load cartridge" menu item)
* Return to the Wii7800 menu
* Select the "Cartridge-specific settings" menu item
* View/edit the settings for the cartridge
Some settings will not be applied until the settings are saved and the
cartridge is reloaded. When one of these settings is modified, a message
will be displayed indicating that this particular setting requires the
cartridge to be reloaded (and the settings saved prior to loading).
Other settings, such as difficulty switch and control settings may not
be applied until the cartridge is reset (or reloaded).
--------------------------------------------
Cartridge/ROM Compatibility
--------------------------------------------
@ -180,8 +198,8 @@ Wii7800 crashes, code dumps, etc.
If you are having issues with Wii7800, please let me know about it via one of
the following locations:
[https://github.com/raz0red/wii7800/issues]
[http://www.wiibrew.org/wiki/Talk:Wii7800]
[http://www.twitchasylum.com/forum/viewtopic.php?t=519]
--------------------------------------------
Special thanks
@ -200,11 +218,30 @@ Team Twiizers : For enabling homebrew
Change log
--------------------------------------------
TBD (0.5)
03/24/20 (0.5)
---------------------
- Partial Expansion Module (XM) support
- XRAM
- XPokey (limited to single Pokey)
- Added support for cartridges with sizes greater than 144k
- Additional bank switching modes and cartridge types
- Multiple bank switching fixes
- Reworked cartridge header detection
- Now properly detects bank switching, RAM, etc.
- Detects Expansion Module (XM)
- Detects High score cartridge
- Detects Pokey at $0450
- Cartridge database
- Fixed incorrect controller settings for Sirius
- Added several homebrew titles (Arkanoid, etc.)
- Added ability to edit cartridge database settings via menu
- Added several new cartridge properties
- Pokey at $0450
- Default difficulty switch settings
- Expansion Module (XM) enabled/disabled
- High score cartridge enabled/disabled
- Database content
- Fixed incorrect controller settings for Sirius, Crossbow,
and Alien Brigade
- Added many homebrew cartridges
- Display enhancements
- Double strike (240p)
- GX+VI mode
@ -212,11 +249,17 @@ TBD (0.5)
- Full widescreen support
- Ability to enable/disable bilinear filter (GX mode)
- Color trap filter
- Multiple default screen sizes
- Hierarchical file navigation support
- USB Support
- SMB (Network support) for loading ROMs
- Multi-save slot support
- Reworked menu system (cartridge-specific settings, etc.)
- Support for launching via WiiFlow (and returning)
- Fixed VSYNC issue which caused initial stutter on PAL games
- Fixed issue occurring when Kangaroo and Holey were enabled (caused
background to be displayed, resulting in large black squares)
- Several audio improvements (eliminated majority of TIA and Pokey pops)
11/16/19 (0.4)
---------------------

View file

@ -2,7 +2,7 @@
<app version="1">
<name>Wii7800</name>
<coder>raz0red</coder>
<version>0.5-SNAPSHOT</version>
<version>0.5</version>
<release_date>000000000000</release_date>
<short_description>Atari 7800 Emulator</short_description>
<long_description>Wii7800 is a port of the ProSystem emulator developed by Greg Stanton.

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,11 @@
#include "wii_atari.h"
#include "wii_app.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#include <string.h>
#define CARTRIDGE_SOURCE "Cartridge.cpp"
@ -40,13 +45,20 @@ std::string cartridge_filename;
byte cartridge_type;
byte cartridge_region;
bool cartridge_pokey;
byte cartridge_controller[2];
bool cartridge_pokey450;
byte cartridge_controller[2] = {1, 1};
byte cartridge_bank;
uint cartridge_flags;
int cartridge_crosshair_x;
int cartridge_crosshair_y;
bool cartridge_dualanalog = false;
bool cartridge_xm = false;
bool cartridge_disable_bios = false;
uint cartridge_hblank = 34;
byte cartridge_left_switch = 1;
byte cartridge_right_switch = 0;
bool cartridge_swap_buttons = false;
bool cartridge_hsc_enabled = false;
// Whether the cartridge has accessed the high score ROM (indicates that the
// SRAM should be persisted when the cartridge is unloaded)
@ -86,22 +98,33 @@ static bool cartridge_CC2(const byte* header) {
}
// ----------------------------------------------------------------------------
// GetBankOffset
// GetBank
// ----------------------------------------------------------------------------
static uint cartridge_GetBankOffset(byte bank) {
static uint cartridge_GetBank(byte bank) {
if ((cartridge_type == CARTRIDGE_TYPE_SUPERCART || cartridge_type == CARTRIDGE_TYPE_SUPERCART_ROM || cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) && cartridge_size <= 65536) {
// for some of these carts, there are only 4 banks. in this case we ignore bit 3
// previously, games of this type had to be doubled. The first 4 banks needed to be duplicated at the end of the ROM
return (bank & 3) * 16384;
return (bank & 3);
}
return bank * 16384;
return bank;
}
// ----------------------------------------------------------------------------
// GetBankOffset
// ----------------------------------------------------------------------------
static uint cartridge_GetBankOffset(byte bank) {
return cartridge_GetBank(bank) * 16384;
}
// ----------------------------------------------------------------------------
// WriteBank
// ----------------------------------------------------------------------------
static void cartridge_WriteBank(word address, byte bank) {
#ifdef TRACE_BANK_SWITCH
net_print_string(NULL, 0, "Bank switch: %d, %d, max:%d\n",
address, cartridge_GetBank(bank), cartridge_size / 16384);
#endif
uint offset = cartridge_GetBankOffset(bank);
if(offset < cartridge_size) {
memory_WriteROM(address, 16384, cartridge_buffer + offset);
@ -109,15 +132,43 @@ static void cartridge_WriteBank(word address, byte bank) {
}
}
static void cartridge_SetTypeBySize(uint size) {
if (size <= 0x10000) {
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_NORMAL;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: no bits and <= 64k: %d, %d\n", old_type, cartridge_type);
#endif
} else if (size == 0x24000 ) {
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: size == 144k: %d, %d\n", old_type, cartridge_type);
#endif
} else if (size == 0x20000 ) {
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: size == 128k: %d, %d\n", old_type, cartridge_type);
#endif
} else {
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: default for > 64k: %d, %d\n", old_type, cartridge_type);
#endif
}
}
// ----------------------------------------------------------------------------
// ReadHeader
// ----------------------------------------------------------------------------
static void cartridge_ReadHeader(const byte* header) {
if( wii_debug )
{
fprintf( stderr, "reading cartridge header:\n" );
}
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Reading cartridge header\n");
#endif
char temp[33] = {0};
for(int index = 0; index < 32; index++) {
@ -148,10 +199,10 @@ static void cartridge_ReadHeader(const byte* header) {
}
}
else {
if(header[53] == 1) {
if(header[53] == 2 /*1*/) { // Wii: Abs and Act were swapped
cartridge_type = CARTRIDGE_TYPE_ABSOLUTE;
}
else if(header[53] == 2) {
else if(header[53] == 1 /*2*/) { // Wii: Abs and Act were swapped
cartridge_type = CARTRIDGE_TYPE_ACTIVISION;
}
else {
@ -159,11 +210,97 @@ static void cartridge_ReadHeader(const byte* header) {
}
}
cartridge_pokey = (header[54] & 1)? true: false;
cartridge_pokey = (header[54]&1)? true: false;
cartridge_pokey450 = (header[54]&0x40)? true : false;
if (cartridge_pokey450) {
cartridge_pokey = true;
}
cartridge_controller[0] = header[55];
cartridge_controller[1] = header[56];
cartridge_region = header[57];
cartridge_flags = 0;
cartridge_xm = (header[63] & 1)? true: false;
cartridge_hsc_enabled = header[58]&0x01;
// Wii: Updates to header interpretation
byte ct1 = header[54];
if(header[53] == 0) {
if ((ct1&0x0a)==0x0a) { // BIT1 and BIT3 (Supercart Large: 2) rom at $4000
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: (0x10) bit1 & bit3: %d, %d\n", old_type, cartridge_type);
#endif
} else if ((ct1&0x12)==0x12) { // BIT1 and BIT4 (Supercart ROM: 4) bank6 at $4000
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: (0x12) bit1 & bit4: %d, %d\n", old_type, cartridge_type);
#endif
} else if ((ct1&0x06)==0x06) { // BIT1 and BIT2 (Supercart RAM: 3) ram at $4000
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART_RAM;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: (0x06) bit1 & bit2: %d, %d\n", old_type, cartridge_type);
#endif
} else if ((ct1&0x02)==0x02) { // BIT1 (Supercart) bank switched
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: (0x01) bit1: %d, %d\n", old_type, cartridge_type);
#endif
} else if (cartridge_size <= 0x10000 && ((ct1&0x04)==0x04)) { // Size < 64k && BIT2 (Normal RAM: ?) ram at $4000 )
int old_type = cartridge_type;
cartridge_type = CARTRIDGE_TYPE_NORMAL_RAM;
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Update: (0x04) bit2: %d, %d\n", old_type, cartridge_type);
#endif
} else {
// Attempt to determine the cartridge type based on its size
cartridge_SetTypeBySize(cartridge_size);
}
}
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Header info:\n");
if (ct1&0x01) {
net_print_string(NULL, 0, " bit0: pokey at $4000\n");
}
if (ct1&0x02) {
net_print_string(NULL, 0, " bit1: supergame bank switched\n");
}
if (ct1&0x04) {
net_print_string(NULL, 0, " bit2: supergame ram at $4000\n");
}
if (ct1&0x08) {
net_print_string(NULL, 0, " bit3: rom at $4000\n");
}
if (ct1&0x10) {
net_print_string(NULL, 0, " bit4: bank 6 at $4000\n");
}
if (ct1&0x20) {
net_print_string(NULL, 0, " bit5: supergame banked ram\n");
}
if (ct1&0x40) {
net_print_string(NULL, 0, " bit6: pokey at $450\n");
}
if (ct1&0x80) {
net_print_string(NULL, 0, " bit7: mirror ram at $4000\n");
}
net_print_string(NULL, 0, " xm: %s\n", (cartridge_xm ? "1" : "0"));
net_print_string(NULL, 0, " pokey: %s\n", (cartridge_pokey ? "1" : "0"));
net_print_string(NULL, 0, " pokey450: %s\n", (cartridge_pokey450 ? "1" : "0"));
net_print_string(NULL, 0, " tv type: %s\n", cartridge_region ? "PAL" : "NTSC");
net_print_string(NULL, 0, " Save device: [%x]%s%s\n", header[58],
((header[58]&0x02) ? " SaveKey/AtariVox": ""),
((header[58]&0x01) ? " HSC": ""));
net_print_string(NULL, 0, " controller1: %d\n", cartridge_controller[0]);
net_print_string(NULL, 0, " controller2: %d\n", cartridge_controller[1]);
net_print_string(NULL, 0, " cartridge_type 53: %d\n", header[53]);
net_print_string(NULL, 0, " cartridge_type 54: %d\n", header[54]);
net_print_string(NULL, 0, " cartridge_size: %d\n", cartridge_size);
net_print_string(NULL, 0, "cartridge_type (from header): %d\n", cartridge_type);
#endif
}
// ----------------------------------------------------------------------------
@ -175,6 +312,10 @@ static bool cartridge_Load(const byte* data, uint size) {
return false;
}
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "actual cartridge_size: %d\n", size);
#endif
cartridge_Release( );
byte header[128] = {0};
@ -193,10 +334,41 @@ static bool cartridge_Load(const byte* data, uint size) {
cartridge_ReadHeader(header);
size -= 128;
offset = 128;
// Several cartridge headers do not have the proper size. So attempt to use the size
// of the file.
if (cartridge_size != size) {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "!!! CARTRIDGE SIZE IN HEADER DOES NOT MATCH !!! : %d %d\n",
cartridge_size, size);
#endif
// Necessary for the following roms:
// Impossible Mission hacks w/ C64 style graphics
if (size%1024 == 0) {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "!!! ROM size is 1k multiple, using ROM size !!! : %d\n",
size);
#endif
cartridge_size = size;
} else {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "!!! ROM size is not 1k multiple, using header size !!! : %d\n",
cartridge_size);
#endif
}
}
}
else {
cartridge_size = size;
// Attempt to guess the cartridge type based on its size
cartridge_SetTypeBySize(size);
}
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "cartridge_type: %d\n", cartridge_type);
net_print_string(NULL, 0, "cartridge_size: %d\n", cartridge_size);
#endif
cartridge_buffer = new byte[cartridge_size];
for(int index = 0; index < cartridge_size; index++) {
@ -381,7 +553,7 @@ static bool cartridge_LoadHighScoreSram()
*/
bool cartridge_LoadHighScoreCart() {
if( !wii_hs_enabled || cartridge_region != REGION_NTSC )
if( !cartridge_hsc_enabled || cartridge_region != REGION_NTSC )
{
// Only load the cart if it is enabled and the region is NTSC
return false;
@ -431,29 +603,37 @@ void cartridge_Store( ) {
case CARTRIDGE_TYPE_NORMAL:
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
break;
case CARTRIDGE_TYPE_SUPERCART:
if(cartridge_GetBankOffset(7) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
}
case CARTRIDGE_TYPE_NORMAL_RAM:
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
memory_ClearROM(16384, 16384);
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
if(cartridge_GetBankOffset(8) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(8));
case CARTRIDGE_TYPE_SUPERCART: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
}
} break;
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(0));
}
break;
case CARTRIDGE_TYPE_SUPERCART_RAM:
if(cartridge_GetBankOffset(7) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
} break;
case CARTRIDGE_TYPE_SUPERCART_RAM: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_ClearROM(16384, 16384);
}
break;
case CARTRIDGE_TYPE_SUPERCART_ROM:
if(cartridge_GetBankOffset(7) < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
} break;
case CARTRIDGE_TYPE_SUPERCART_ROM: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(6));
}
break;
} break;
case CARTRIDGE_TYPE_ABSOLUTE:
memory_WriteROM(16384, 16384, cartridge_buffer);
memory_WriteROM(32768, 32768, cartridge_buffer + cartridge_GetBankOffset(2));
@ -474,19 +654,24 @@ void cartridge_Store( ) {
// Write
// ----------------------------------------------------------------------------
void cartridge_Write(word address, byte data) {
#if 0
net_print_string(NULL, 0, "Cartridge write: %d, %d\n", address, data);
#endif
switch(cartridge_type) {
case CARTRIDGE_TYPE_SUPERCART:
case CARTRIDGE_TYPE_SUPERCART_RAM:
case CARTRIDGE_TYPE_SUPERCART_ROM:
if(address >= 32768 && address < 49152 && data < 9) {
case CARTRIDGE_TYPE_SUPERCART_ROM: {
uint maxbank = cartridge_size / 16384;
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
cartridge_StoreBank(data);
}
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
if(address >= 32768 && address < 49152 && data < 9) {
} break;
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
uint maxbank = cartridge_size / 16384;
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
cartridge_StoreBank(data + 1);
}
break;
} break;
case CARTRIDGE_TYPE_ABSOLUTE:
if(address == 32768 && (data == 1 || data == 2)) {
cartridge_StoreBank(data - 1);
@ -499,6 +684,7 @@ void cartridge_Write(word address, byte data) {
break;
}
#if 0 // WIi: Moved to Memory.cpp
if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) {
switch(address) {
case POKEY_AUDF1:
@ -533,6 +719,7 @@ void cartridge_Write(word address, byte data) {
break;
}
}
#endif
}
// ----------------------------------------------------------------------------
@ -580,21 +767,30 @@ void cartridge_Release( ) {
cartridge_buffer = NULL;
//
// WII
// Wii
//
// These values need to be reset so that moving between carts works
// consistently. This seems to be a ProSystem emulator bug.
//
cartridge_title = "";
cartridge_type = 0;
cartridge_region = 0;
cartridge_pokey = 0;
memset( cartridge_controller, 0, sizeof( cartridge_controller ) );
cartridge_pokey450 = 0;
cartridge_xm = false;
// Default to joysticks
memset( cartridge_controller, 1, sizeof( cartridge_controller ) );
cartridge_bank = 0;
cartridge_flags = 0;
cartridge_disable_bios = false;
cartridge_crosshair_x = 0;
cartridge_crosshair_y = 0;
high_score_set = false;
cartridge_hblank = 34;
cartridge_hblank = HBLANK_DEFAULT;
cartridge_dualanalog = false;
cartridge_left_switch = 1;
cartridge_right_switch = 0;
cartridge_swap_buttons = false;
cartridge_hsc_enabled = false;
}
}

View file

@ -31,6 +31,7 @@
#define CARTRIDGE_TYPE_SUPERCART_ROM 4
#define CARTRIDGE_TYPE_ABSOLUTE 5
#define CARTRIDGE_TYPE_ACTIVISION 6
#define CARTRIDGE_TYPE_NORMAL_RAM 7
#define CARTRIDGE_CONTROLLER_NONE 0
#define CARTRIDGE_CONTROLLER_JOYSTICK 1
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
@ -46,6 +47,8 @@
#include "Pokey.h"
#include "Archive.h"
#define HBLANK_DEFAULT 34
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int uint;
@ -66,9 +69,15 @@ extern std::string cartridge_filename;
extern byte cartridge_type;
extern byte cartridge_region;
extern bool cartridge_pokey;
extern bool cartridge_pokey450;
extern bool cartridge_xm;
extern byte cartridge_controller[2];
extern byte cartridge_bank;
extern uint cartridge_flags;
extern bool cartridge_disable_bios;
extern byte cartridge_left_switch;
extern byte cartridge_right_switch;
extern bool cartridge_swap_buttons;
// The x offset for the lightgun crosshair (allows per cartridge adjustments)
extern int cartridge_crosshair_x;
@ -78,6 +87,8 @@ extern int cartridge_crosshair_y;
extern uint cartridge_hblank;
// Whether the cartridge supports dual analog
extern bool cartridge_dualanalog;
// Whether the high score cart is enabled
extern bool cartridge_hsc_enabled;
/*
* Loads the high score cartridge

View file

@ -31,8 +31,14 @@
#include "wii_app_common.h"
#endif
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define DATABASE_SOURCE "Database.cpp"
bool cart_in_db = false;
bool database_enabled = true;
std::string database_filename = "./prosystem.dat";
@ -48,8 +54,15 @@ char database_loc[WII_MAX_PATH] = "";
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
bool database_Load(std::string digest) {
bool database_Load(std::string digest) {
cart_in_db = false;
if(database_enabled) {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "attempting to find db entry with hash: [%s]\n",
digest.c_str());
#endif
#ifndef WII
FILE* file = fopen(database_filename.c_str(), "r");
#else
@ -63,21 +76,29 @@ bool database_Load(std::string digest) {
return false;
}
// max count of items in the database
static int count = 17;
bool found = false;
char buffer[256];
while (fgets(buffer, 256, file) != NULL) {
std::string line = buffer;
if (line.compare(1, 32, digest.c_str()) == 0) {
found = true;
std::string entry[11];
for (int index = 0; index < 11; index++) {
cart_in_db = true;
std::string entry[count];
for (int index = 0; index < count; index++) {
buffer[0] = '\0';
fgets(buffer, 256, file);
if (strchr(buffer, '[')) {
// Passed the current game in DB
break;
}
entry[index] = common_Remove(buffer, '\r');
entry[index] = common_Remove(entry[index], '\n');
}
cartridge_title = database_GetValue(entry[0]);
cartridge_title = database_GetValue(entry[0]);
cartridge_type = common_ParseByte(database_GetValue(entry[1]));
cartridge_pokey = common_ParseBool(database_GetValue(entry[2]));
cartridge_controller[0] =
@ -91,7 +112,7 @@ bool database_Load(std::string digest) {
// Optionally load the lightgun crosshair offsets, hblank, dual
// analog
//
for (int index = 7; index < 11; index++) {
for (int index = 7; index < count; index++) {
if (entry[index].find("crossx") != std::string::npos) {
cartridge_crosshair_x =
common_ParseInt(database_GetValue(entry[index]));
@ -108,8 +129,38 @@ bool database_Load(std::string digest) {
cartridge_dualanalog =
common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("pokey450") != std::string::npos) {
cartridge_pokey450 =
common_ParseBool(database_GetValue(entry[index]));
if (cartridge_pokey450) {
cartridge_pokey = true;
}
}
if (entry[index].find("xm") != std::string::npos) {
cartridge_xm =
common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("disablebios") != std::string::npos) {
cartridge_disable_bios =
common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("leftswitch") != std::string::npos) {
cartridge_left_switch =
common_ParseByte(database_GetValue(entry[index]));
}
if (entry[index].find("rightswitch") != std::string::npos) {
cartridge_right_switch =
common_ParseByte(database_GetValue(entry[index]));
}
if (entry[index].find("swapbuttons") != std::string::npos) {
cartridge_swap_buttons =
common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("hsc") != std::string::npos) {
cartridge_hsc_enabled =
common_ParseBool(database_GetValue(entry[index]));
}
}
break;
}
}

View file

@ -35,5 +35,6 @@ extern void database_Initialize( );
extern bool database_Load(std::string digest);
extern bool database_enabled;
extern std::string database_filename;
extern bool cart_in_db;
#endif

115
src/ExpansionModule.cpp Normal file
View file

@ -0,0 +1,115 @@
/*
Memory map:
POKEY1 $0450 $045F 16 bytes
POKEY2* $0460 $046F 16 bytes
XCTRL $0470 $047F 1 byte
RAM $4000 $7FFF 16384 bytes
XCTRL Bit Description
+-------------------------------+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------+
| | | | | | | |
| | | | | | | +-- Bank select bit 0 \
| | | | | | +------ Bank select bit 1 | Totally 128 KByte in 16 KByte banks
| | | | | +---------- Bank select bit 3 /
| | | | +-------------- Enable memory bit (1 = Memory enabled, 0 after power on)
| | | +------------------ Enable POKEY bit** (1 = POKEY enabled, 0 after power on)
| | |
NA NA NA = Not Available or Not Used
* = Can be mounted piggy back on the first POKEY. Description how to do this will come when i have tried it out.
** This bit controls both POKEY chip select signals.
The mapping is totally non compatible with pretty much everything.
There is a bank select latch located at $0470 and the POKEY is located at $0450
(There's also a chip select output ($0460) on the PLD which alows you to simply piggy back a second POKEY).
Since the PLD is reconfigurable I could map the POKEY (or the RAM for that matter) to pretty much anything
if you wanted to. However since the PLD is soldered under the POKEY this needs to be configured before delivery.
*/
#include <string.h>
#include "ExpansionModule.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
byte xm_ram[XM_RAM_SIZE] = {0};
byte xm_reg = 0;
byte xm_bank = 0;
bool xm_pokey_enabled = false;
bool xm_mem_enabled = false;
void xm_Reset() {
memset(xm_ram, 0, XM_RAM_SIZE);
xm_bank = 0;
xm_reg = 0;
xm_mem_enabled = false;
xm_pokey_enabled = false;
}
byte xm_Read(word address) {
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
byte b = pokey_GetRegister(0x4000 + (address - 0x0450));
#if 0
net_print_string(NULL, 0, "Read from Pokey1: %x %d\n", address, b);
#endif
return b;
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
byte b = pokey_GetRegister(0x4000 + (address - 0x0460));
#if 0
net_print_string(NULL, 0, "Read from Pokey2: %x %d\n", address, b);
#endif
return b;
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
byte b = xm_ram[(xm_bank * 0x4000) + (address - 0x4000)];
#if 0
net_print_string(NULL, 0, "Read from XM RAM: %x %d\n", address, b);
#endif
return b;
} else if (address >= 0x0470 && address < 0x0480) {
#if 0
net_print_string(NULL, 0, "Read from XCTRL 0x0470: %x\n", address);
#endif
// TODO: Should the value be returned?
}
return 0;
}
void xm_Write(word address, byte data) {
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
#if 0
net_print_string(NULL, 0, "Wrote to Pokey1: %x %d\n", address, data);
#endif
pokey_SetRegister(0x4000 + (address - 0x0450), data);
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
#if 0
net_print_string(NULL, 0, "Wrote to Pokey2: %x %d\n", address, data);
#endif
pokey_SetRegister(0x4000 + (address - 0x0460), data);
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
#if 0
net_print_string(NULL, 0, "Wrote to XM RAM: %x %d\n", address, data);
#endif
xm_ram[(xm_bank * 0x4000) + (address - 0x4000)] = data;
} else if (address >= 0x0470 && address < 0x0480) {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Wrote to XCTRL 0x0470: %x %d\n", address,
data);
#endif
xm_reg = data;
xm_bank = xm_reg & 7;
xm_pokey_enabled = (xm_reg & 0x10);
xm_mem_enabled = (xm_reg & 0x08);
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "xm_reg: %d, xm_bank: %d, xm_pokey_enabled: %d, xm_mem_enabled: %d\n",
xm_reg, xm_bank, xm_pokey_enabled, xm_mem_enabled);
#endif
}
}

19
src/ExpansionModule.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef EXPANSIONMODULE_H
#define EXPANSIONMODULE_H
#include "Cartridge.h"
#include "Memory.h"
#define XM_RAM_SIZE 0x20000
extern byte xm_ram[XM_RAM_SIZE];
extern bool xm_pokey_enabled;
extern bool xm_mem_enabled;
extern byte xm_reg;
extern byte xm_bank;
void xm_Reset();
byte xm_Read(word address);
void xm_Write(word address, byte data);
#endif

View file

@ -23,6 +23,12 @@
// Maria.c
// ----------------------------------------------------------------------------
#include "Maria.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define MARIA_LINERAM_SIZE 160
extern unsigned char* wii_sdl_get_blit_addr();
@ -50,7 +56,7 @@ static byte maria_wmode;
// StoreCell
// ----------------------------------------------------------------------------
static inline void maria_StoreCell(byte data) {
if(maria_horizontal < MARIA_LINERAM_SIZE) {
if(maria_horizontal < MARIA_LINERAM_SIZE) {
if(data) {
maria_lineRAM[maria_horizontal] = maria_palette | data;
}
@ -61,13 +67,12 @@ static inline void maria_StoreCell(byte data) {
}
}
}
maria_horizontal++;
}
maria_horizontal++;}
// ----------------------------------------------------------------------------
// StoreCell
// ----------------------------------------------------------------------------
static inline void maria_StoreCell(byte high, byte low) {
static inline void maria_StoreCell(byte high, byte low) {
if(maria_horizontal < MARIA_LINERAM_SIZE) {
if(low || high) {
maria_lineRAM[maria_horizontal] = maria_palette & 16 | high | low;
@ -118,8 +123,11 @@ static inline void maria_StoreGraphic( ) {
byte data = memory_ram[maria_pp.w];
if(maria_wmode) {
if(maria_IsHolyDMA( )) {
#if 0 // Wii: disabled due to rendering in Kangaroo mode
maria_StoreCell(0, 0);
maria_StoreCell(0, 0);
#endif
maria_horizontal+=2;
}
else {
maria_StoreCell((data & 12), (data & 192) >> 6);
@ -128,17 +136,20 @@ static inline void maria_StoreGraphic( ) {
}
else {
if(maria_IsHolyDMA( )) {
#if 0 // Wii: disabled due to rendering in Kangaroo mode
maria_StoreCell(0);
maria_StoreCell(0);
maria_StoreCell(0);
maria_StoreCell(0);
#endif
maria_horizontal+=4;
}
else {
maria_StoreCell((data & 192) >> 6);
maria_StoreCell((data & 48) >> 4);
maria_StoreCell((data & 12) >> 2);
maria_StoreCell(data & 3);
}
}
}
maria_pp.w++;
}
@ -149,6 +160,7 @@ static inline void maria_StoreGraphic( ) {
static inline void maria_WriteLineRAM(byte* buffer) {
byte rmode = memory_ram[CTRL] & 3;
if(rmode == 0) {
// 160A/B
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
word color;
@ -167,6 +179,7 @@ static inline void maria_WriteLineRAM(byte* buffer) {
}
}
else if(rmode == 2) {
// 320B/D
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 16) | ((maria_lineRAM[index + 0] & 8) >> 3) | ((maria_lineRAM[index + 0] & 2)));
@ -180,6 +193,7 @@ static inline void maria_WriteLineRAM(byte* buffer) {
}
}
else if(rmode == 3) {
// 320A/C
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 30));

View file

@ -25,6 +25,12 @@
#include "wii_main.h"
#include "Memory.h"
#include "ExpansionModule.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
byte memory_ram[MEMORY_SIZE] = {0};
byte memory_rom[MEMORY_SIZE] = {0};
@ -51,11 +57,24 @@ void memory_Reset( ) {
// Read
// ----------------------------------------------------------------------------
byte memory_Read(word address) {
#if 0
net_print_string(NULL, 0, "Memory read: %d\n", address);
#endif
byte tmp_byte;
if( cartridge_pokey && address == POKEY_RANDOM )
{
return pokey_GetRegister( POKEY_RANDOM );
if (cartridge_xm) {
if ((address >= 0x0470 && address < 0x0480) ||
(xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))) {
return xm_Read(address);
}
}
if (cartridge_pokey && (
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
return pokey_GetRegister(
cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address);
}
switch ( address ) {
@ -80,6 +99,25 @@ byte memory_Read(word address) {
// Write
// ----------------------------------------------------------------------------
void memory_Write(word address, byte data) {
#if 0
net_print_string(NULL, 0, "Memory write: %d, %d\n", address, data);
#endif
if (cartridge_xm &&
((address >= 0x0470 && address < 0x0480) ||
((xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))))) {
xm_Write(address, data);
return;
}
if (cartridge_pokey && (
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
pokey_SetRegister(
(cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address), data);
return;
}
if(!memory_rom[address]) {
@ -139,11 +177,11 @@ if( address >= 0x1000 && address <= 0x17FF )
case SWCHB:
/*gdement: Writing here actually writes to DRB inside the RIOT chip.
This value only indirectly affects output of SWCHB.*/
riot_SetDRB(data);
break;
riot_SetDRB(data);
break;
case SWCHA:
riot_SetDRA(data);
riot_SetDRA(data);
break;
case TIM1T:
case TIM1T | 0x8:
@ -186,7 +224,7 @@ if( address >= 0x1000 && address <= 0x17FF )
// ----------------------------------------------------------------------------
// WriteROM
// ----------------------------------------------------------------------------
void memory_WriteROM(word address, word size, const byte* data) {
void memory_WriteROM(word address, uint size, const byte* data) {
if((address + size) <= MEMORY_SIZE && data != NULL) {
for(uint index = 0; index < size; index++) {
memory_ram[address + index] = data[index];
@ -198,7 +236,7 @@ void memory_WriteROM(word address, word size, const byte* data) {
// ----------------------------------------------------------------------------
// ClearROM
// ----------------------------------------------------------------------------
void memory_ClearROM(word address, word size) {
void memory_ClearROM(word address, uint size) {
if((address + size) <= MEMORY_SIZE) {
for(uint index = 0; index < size; index++) {
memory_ram[address + index] = 0;

View file

@ -39,8 +39,8 @@ typedef unsigned int uint;
extern void memory_Reset( );
extern byte memory_Read(word address);
extern void memory_Write(word address, byte data);
extern void memory_WriteROM(word address, word size, const byte* data);
extern void memory_ClearROM(word address, word size);
extern void memory_WriteROM(word address, uint size, const byte* data);
extern void memory_ClearROM(word address, uint size);
extern byte memory_ram[MEMORY_SIZE];
extern byte memory_rom[MEMORY_SIZE];

View file

@ -38,6 +38,12 @@
// ----------------------------------------------------------------------------
// Pokey.cpp
// ----------------------------------------------------------------------------
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#include <stdlib.h>
#include <SDL.h>
#include "Pokey.h"
@ -70,7 +76,7 @@
#define SK_RESET 0x03
byte pokey_buffer[POKEY_BUFFER_SIZE] = {0};
uint pokey_size = 524;
uint pokey_size = (POKEY_BUFFER_SIZE - 512); // 524
static uint pokey_frequency = 1787520;
static uint pokey_sampleRate = 31440;
@ -101,6 +107,13 @@ static uint r17;
static byte SKCTL;
byte RANDOM;
#ifdef WII_NETTRACE
int pokey_debug_count = 100;
#endif
byte POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228};
static int pot_scanline;
static ullong random_scanline_counter;
static ullong prev_random_scanline_counter;
@ -129,6 +142,13 @@ void pokey_setSampleRate( uint rate ) {
// Reset
// ----------------------------------------------------------------------------
void pokey_Reset( ) {
#ifdef WII_NETTRACE
pokey_debug_count = 100;
#endif
pot_scanline = 0;
pokey_soundCntr = 0;
for(int index = 0; index < POKEY_POLY17_SIZE; index++) {
pokey_poly17[index] = rand( ) & 1;
}
@ -153,6 +173,10 @@ void pokey_Reset( ) {
pokey_audf[channel] = 0;
}
for(int i = 0; i < 8; i++) {
POT_input[i] = 228;
}
pokey_audctl = 0;
pokey_baseMultiplier = POKEY_DIV_64;
@ -176,12 +200,34 @@ void pokey_Frame() {
/* Called prior to each scanline */
void pokey_Scanline() {
random_scanline_counter += CYCLES_PER_SCANLINE;
if (pot_scanline < 228)
pot_scanline++;
}
byte pokey_GetRegister(word address) {
#ifdef WII_NETTRACE
if ((pokey_debug_count--)>0)
net_print_string(NULL, 0, "pokey_getRegister: %d\n", address);
#endif
byte data = 0;
byte addr = address & 0x0f;
if (addr < 8) {
byte b = POT_input[addr];
if (b <= pot_scanline)
return b;
return pot_scanline;
}
switch (address) {
case POKEY_ALLPOT: {
byte b = 0;
for (int i = 0; i < 8; i++)
if (POT_input[addr] <= pot_scanline)
b &= ~(1 << i); /* reset bit if pot value known */
return b;
}
case POKEY_RANDOM:
ullong curr_scanline_counter =
( random_scanline_counter + prosystem_cycles + prosystem_extra_cycles );
@ -210,7 +256,6 @@ byte pokey_GetRegister(word address) {
RANDOM = RANDOM ^ 0xff;
data = RANDOM;
break;
}
@ -221,11 +266,22 @@ byte pokey_GetRegister(word address) {
// SetRegister
// ----------------------------------------------------------------------------
void pokey_SetRegister(word address, byte value) {
#ifdef WII_NETTRACE
if ((pokey_debug_count--)>0)
net_print_string(NULL, 0, "pokey_setRegister: %d %d\n", address, value);
#endif
byte channelMask;
switch(address) {
case POKEY_POTGO:
if (!(SKCTL & 4))
pot_scanline = 0; /* slow pot mode */
return;
case POKEY_SKCTLS:
SKCTL = value;
if (value & 4)
pot_scanline = 228; /* fast pot mode - return results immediately */
return;
case POKEY_AUDF1:
@ -372,8 +428,14 @@ void pokey_SetRegister(word address, byte value) {
for(byte channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
if(channelMask & (1 << channel)) {
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) || ((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) || (pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) ||
((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) ||
(pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
#if 1 // WII
pokey_outVol[channel] = 1;
#else
pokey_outVol[channel] = pokey_audc[channel] & POKEY_VOLUME_MASK;
#endif
pokey_divideCount[channel] = 0x7fffffff;
pokey_divideMax[channel] = 0x7fffffff;
}
@ -469,7 +531,6 @@ void pokey_Process(uint length)
// Clear
// ----------------------------------------------------------------------------
void pokey_Clear( ) {
for(int index = 0; index < POKEY_BUFFER_SIZE; index++) {
pokey_buffer[index] = 0;
}
pokey_soundCntr = 0;
memset(pokey_buffer, 0, POKEY_BUFFER_SIZE);
}

View file

@ -50,28 +50,28 @@
#define POKEY_AUDC3 0x4005
#define POKEY_AUDF4 0x4006
#define POKEY_AUDC4 0x4007
#define POKEY_AUDCTL 0x4008
#define POKEY_STIMER 0x4009
#define POKEY_SKRES 0x400a
#define POKEY_POTGO 0x400b
#define POKEY_SEROUT 0x400d
#define POKEY_IRQEN 0x400e
#define POKEY_SKCTLS 0x400f
#define POKEY_POT0 0x4000
#define POKEY_POT1 0x4001
#define POKEY_POT2 0x4002
#define POKEY_POT3 0x4003
#define POKEY_POT4 0x4004
#define POKEY_POT5 0x4005
#define POKEY_POT6 0x4006
#define POKEY_POT7 0x4007
#define POKEY_ALLPOT 0x4008
#define POKEY_KBCODE 0x4009
#define POKEY_RANDOM 0x400a
#define POKEY_SERIN 0x400d
#define POKEY_IRQST 0x400e
#define POKEY_SKSTAT 0x400f
#define POKEY_AUDCTL 0x4008
#define POKEY_STIMER 0x4009
#define POKEY_SKRES 0x400a
#define POKEY_POTGO 0x400b
#define POKEY_SEROUT 0x400d
#define POKEY_IRQEN 0x400e
#define POKEY_SKCTLS 0x400f
#define POKEY_POT0 0x4000
#define POKEY_POT1 0x4001
#define POKEY_POT2 0x4002
#define POKEY_POT3 0x4003
#define POKEY_POT4 0x4004
#define POKEY_POT5 0x4005
#define POKEY_POT6 0x4006
#define POKEY_POT7 0x4007
#define POKEY_ALLPOT 0x4008
#define POKEY_KBCODE 0x4009
#define POKEY_RANDOM 0x400a
#define POKEY_SERIN 0x400d
#define POKEY_IRQST 0x400e
#define POKEY_SKSTAT 0x400f
typedef unsigned char byte;

View file

@ -32,6 +32,11 @@
#include "wii_sdl.h"
#include "wii_atari.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define PRO_SYSTEM_SOURCE "ProSystem.cpp"
#define PRO_SYSTEM_STATE_HEADER "PRO-SYSTEM STATE"
@ -63,6 +68,8 @@ void prosystem_Reset( ) {
tia_Reset( );
pokey_Clear( );
pokey_Reset( );
xm_Reset( );
memory_Reset( );
maria_Clear( );
maria_Reset( );
@ -109,20 +116,18 @@ bool dbg_cycle_stealing;
// ExecuteFrame
// ----------------------------------------------------------------------------
#if 0
extern float wii_orient_roll;
#endif
void prosystem_ExecuteFrame(const byte* input)
{
// Is WSYNC enabled for the current frame?
bool wsync =
( ( wii_cart_wsync == CART_MODE_ENABLED ) ||
( ( wii_cart_wsync == CART_MODE_AUTO ) &&
( !( cartridge_flags & CARTRIDGE_WSYNC_MASK ) ) ) );
bool wsync = !( cartridge_flags & CARTRIDGE_WSYNC_MASK );
dbg_wsync = wsync;
// Is Maria cycle stealing enabled for the current frame?
bool cycle_stealing =
( ( wii_cart_cycle_stealing == CART_MODE_ENABLED ) ||
( ( wii_cart_cycle_stealing == CART_MODE_AUTO ) &&
( !( cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK ) ) ) );
bool cycle_stealing = !( cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK );
dbg_cycle_stealing = cycle_stealing;
// Is the lightgun enabled for the current frame?
@ -137,10 +142,18 @@ void prosystem_ExecuteFrame(const byte* input)
dbg_maria_cycles = 0; // debug
dbg_p6502_cycles = 0; // debug
if( cartridge_pokey ) pokey_Frame();
if( cartridge_pokey || cartridge_xm ) pokey_Frame();
for( maria_scanline = 1; maria_scanline <= prosystem_scanlines; maria_scanline++ )
{
#if 0
if ((int)wii_orient_roll == maria_scanline) {
memory_ram[INPT2] &= 0x7f;
} else {
memory_ram[INPT2] |= 0x80;
}
#endif
if( maria_scanline == maria_displayArea.top )
{
memory_ram[MSTAT] = 0;
@ -253,12 +266,12 @@ void prosystem_ExecuteFrame(const byte* input)
if( lightgun ) prosystem_FireLightGun();
tia_Process(2);
if( cartridge_pokey )
if( cartridge_pokey || cartridge_xm )
{
pokey_Process(2);
}
if( cartridge_pokey ) pokey_Scanline();
if( cartridge_pokey || cartridge_xm ) pokey_Scanline();
}
prosystem_frame++;
@ -280,8 +293,8 @@ bool prosystem_Save(std::string filename, bool compress)
logger_LogError("Filename is invalid.", PRO_SYSTEM_SOURCE);
return false;
}
if (! loc_buffer) loc_buffer = (byte *)malloc(33000 * sizeof(byte));
if (!loc_buffer) loc_buffer = (byte *)malloc((33000 + XM_RAM_SIZE + 4) * sizeof(byte));
logger_LogInfo("Saving game state to file " + filename + ".");
@ -329,38 +342,47 @@ bool prosystem_Save(std::string filename, bool compress)
loc_buffer[size++] = riot_dra;
loc_buffer[size++] = riot_drb;
loc_buffer[size++] = riot_timing;
loc_buffer[size++] = ( 0xff & ( riot_timer >> 8 ) );
loc_buffer[size++] = ( 0xff & riot_timer );
loc_buffer[size++] = (0xff & (riot_timer >> 8));
loc_buffer[size++] = (0xff & riot_timer);
loc_buffer[size++] = riot_intervals;
loc_buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) );
loc_buffer[size++] = ( 0xff & riot_clocks );
loc_buffer[size++] = (0xff & (riot_clocks >> 8));
loc_buffer[size++] = (0xff & riot_clocks);
// XM (if applicable)
if (cartridge_xm) {
loc_buffer[size++] = xm_reg;
loc_buffer[size++] = xm_bank;
loc_buffer[size++] = xm_pokey_enabled;
loc_buffer[size++] = xm_mem_enabled;
#if 0
if(!compress) {
#endif
FILE* file = fopen(filename.c_str( ), "wb");
if(file == NULL) {
logger_LogError("Failed to open the file " + filename + " for writing.", PRO_SYSTEM_SOURCE);
return false;
net_print_string(NULL, 0, "Wrote XM: xm_reg: %d, xm_bank: %d, xm_pokey_enabled: %d, xm_mem_enabled: %d\n",
xm_reg, xm_bank, xm_pokey_enabled, xm_mem_enabled);
#endif
for (index = 0; index < XM_RAM_SIZE; index++) {
loc_buffer[size + index] = xm_ram[index];
}
if(fwrite(loc_buffer, 1, size, file) != size) {
size += XM_RAM_SIZE;
}
FILE* file = fopen(filename.c_str(), "wb");
if (file == NULL) {
logger_LogError("Failed to open the file " + filename + " for writing.",
PRO_SYSTEM_SOURCE);
return false;
}
if (fwrite(loc_buffer, 1, size, file) != size) {
fclose(file);
logger_LogError("Failed to write the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
logger_LogError(
"Failed to write the save state data to the file " + filename + ".",
PRO_SYSTEM_SOURCE);
return false;
}
fflush(file);
fclose(file);
#if 0
}
else {
if(!archive_Compress(filename.c_str( ), "Save.sav", loc_buffer, size)) {
logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
return false;
}
}
#endif
fflush(file);
fclose(file);
return true;
}
@ -375,7 +397,7 @@ bool prosystem_Load(const std::string filename) {
return false;
}
if (! loc_buffer) loc_buffer = (byte *)malloc(33000 * sizeof(byte));
if (!loc_buffer) loc_buffer = (byte *)malloc((33000 + XM_RAM_SIZE + 4) * sizeof(byte));
logger_LogInfo("Loading game state from file " + filename + ".");
@ -400,10 +422,11 @@ bool prosystem_Load(const std::string filename) {
return false;
}
if( size != 16445 &&
size != 32829 &&
size != 16453 &&
size != 32837 ) {
if( size != 16445 && size != 32829 && /* no RIOT */
size != 16453 && size != 32837 && /* with RIOT */
size != (16453 + 4 + XM_RAM_SIZE) && /* XM without supercart ram */
size != (32837 + 4 + XM_RAM_SIZE)) /* XM with supercart ram */
{
fclose(file);
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
@ -416,9 +439,6 @@ bool prosystem_Load(const std::string filename) {
}
fclose(file);
}
else if(size == 16445 || size == 32829 ) {
archive_Uncompress(filename, loc_buffer, size);
}
else {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
@ -468,28 +488,55 @@ bool prosystem_Load(const std::string filename) {
offset += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
if(size != 32829 && size != 32837) {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
for(index = 0; index < 16384; index++) {
memory_ram[16384 + index] = loc_buffer[offset + index];
if (size != 32829 && /* no RIOT */
size != 32837 && /* with RIOT */
size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ {
logger_LogError("Save state file has an invalid size.",
PRO_SYSTEM_SOURCE);
return false;
}
for (index = 0; index < 16384; index++) {
memory_ram[16384 + index] = loc_buffer[offset + index];
}
offset += 16384;
}
}
if( size == 16453 || size == 32837 )
{
if (size == 16453 || /* no supercart ram */
size == 32837 || /* supercart ram */
size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */
size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ {
// RIOT state
riot_dra = loc_buffer[offset++];
riot_drb = loc_buffer[offset++];
riot_timing = loc_buffer[offset++];
riot_timer = ( loc_buffer[offset++] << 8 );
riot_timer = (loc_buffer[offset++] << 8);
riot_timer |= loc_buffer[offset++];
riot_intervals = loc_buffer[offset++];
riot_clocks = ( loc_buffer[offset++] << 8 );
riot_clocks = (loc_buffer[offset++] << 8);
riot_clocks |= loc_buffer[offset++];
}
// XM (if applicable)
if (cartridge_xm) {
if ((size != (16453 + 4 + XM_RAM_SIZE)) &&
(size != (32837 + 4 + XM_RAM_SIZE))) {
logger_LogError("Save state file has an invalid size.",
PRO_SYSTEM_SOURCE);
return false;
}
xm_reg = loc_buffer[offset++];
xm_bank = loc_buffer[offset++];
xm_pokey_enabled = loc_buffer[offset++];
xm_mem_enabled = loc_buffer[offset++];
#if 0
net_print_string(NULL, 0, "Read XM: xm_reg: %d, xm_bank: %d, xm_pokey_enabled: %d, xm_mem_enabled: %d\n",
xm_reg, xm_bank, xm_pokey_enabled, xm_mem_enabled);
#endif
for (index = 0; index < XM_RAM_SIZE; index++) {
xm_ram[index] = loc_buffer[offset++];
}
}
return true;

View file

@ -38,6 +38,7 @@
#include "Archive.h"
#include "Tia.h"
#include "Pokey.h"
#include "ExpansionModule.h"
typedef unsigned char byte;
typedef unsigned short word;

View file

@ -189,8 +189,10 @@ void region_Reset( ) {
palette_Load(REGION_PALETTE_PAL); // Added check for default - bberlin
prosystem_frequency = REGION_FREQUENCY_PAL;
prosystem_scanlines = REGION_SCANLINES_PAL;
#ifndef WII
tia_size = 624;
pokey_size = 624;
pokey_size = 624;
#endif
}
else {
maria_displayArea = REGION_DISPLAY_AREA_NTSC;
@ -199,8 +201,10 @@ void region_Reset( ) {
palette_Load(REGION_PALETTE_NTSC); // Added check for default - bberlin
prosystem_frequency = REGION_FREQUENCY_NTSC;
prosystem_scanlines = REGION_SCANLINES_NTSC;
#ifndef WII
tia_size = 524;
pokey_size = 524;
#endif
}
pokey_setSampleRate( ( prosystem_scanlines * prosystem_frequency ) << 1 );
pokey_setSampleRate((prosystem_scanlines * prosystem_frequency) << 1);
}

View file

@ -27,6 +27,11 @@
#include <SDL.h>
#include "wii_direct_sound.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define SOUND_SOURCE "Sound.cpp"
int wii_sound_length = 0;
@ -77,17 +82,16 @@ static void sound_Resample(const byte* source, byte* target, int length) {
int measurement = sound_format.nSamplesPerSec;
int sourceIndex = 0;
int targetIndex = 0;
int max = ( ( prosystem_frequency * prosystem_scanlines ) << 1 );
while(targetIndex < length) {
if(measurement >= max) {
target[targetIndex++] = source[sourceIndex];
measurement -= max;
}
else {
sourceIndex++;
measurement += sound_format.nSamplesPerSec;
}
int max = ((prosystem_frequency * prosystem_scanlines) << 1);
while (targetIndex < length) {
if (measurement >= max) {
target[targetIndex++] = source[sourceIndex];
measurement -= max;
} else {
sourceIndex++;
measurement += sound_format.nSamplesPerSec;
}
}
}
@ -112,26 +116,68 @@ bool sound_SetFormat(WAVEFORMATEX format) {
// Store
// ----------------------------------------------------------------------------
byte sample[MAX_BUFFER_SIZE] = {0};
byte pokeySample[MAX_BUFFER_SIZE] = {0};
#ifdef TRACE_SOUND
static int maxTia = 0, minTia = 0, maxPokey = 0, minPokey = 0;
static u64 sumTia = 0, sumPokey = 0;
static int scount = 0;
static u64 stotalCount = 0;
#endif
bool sound_Store( ) {
bool pokey = (cartridge_pokey || xm_pokey_enabled);
if( sound_muted ) sound_SetMuted( false );
byte sample[MAX_BUFFER_SIZE];
memset( sample, 0, MAX_BUFFER_SIZE );
uint length = 48000 / prosystem_frequency; /* sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); */ /* 48000 / prosystem_frequency */
sound_Resample(tia_buffer, sample, length);
tia_Clear(); // WII
if(cartridge_pokey) {
byte pokeySample[MAX_BUFFER_SIZE];
if(pokey) {
memset( pokeySample, 0, MAX_BUFFER_SIZE );
sound_Resample(pokey_buffer, pokeySample, length);
sound_Resample(pokey_buffer, pokeySample, length);
for(uint index = 0; index < length; index++) {
sample[index] += pokeySample[index];
sample[index] = sample[index] / 2;
#ifdef TRACE_SOUND
stotalCount++;
if (sample[index] > maxTia) maxTia = sample[index];
if (sample[index] < minTia) minTia = sample[index];
if (pokeySample[index] > maxPokey) maxPokey = pokeySample[index];
if (pokeySample[index] < minPokey) minPokey = pokeySample[index];
sumTia += sample[index];
sumPokey += pokeySample[index];
#endif
u32 sound = sample[index] + pokeySample[index];
sample[index] = sound >> 1;
}
}
}
else {
for(uint index = 0; index < length; index++) {
#ifdef TRACE_SOUND
stotalCount++;
sumTia += sample[index];
if (sample[index] > maxTia) maxTia = sample[index];
if (sample[index] < minTia) minTia = sample[index];
#endif
sample[index] = sample[index] * 0.75; //>> 1;
}
}
pokey_Clear(); // WII
wii_storeSound( sample, length );
wii_storeSound( sample, length );
#ifdef TRACE_SOUND
if (scount++ == 60) {
net_print_string(NULL, 0, "Pokey: max %d, min %d, avg: %f (sum:%llu, count:%llu)\n",
maxPokey, minPokey, (sumPokey/(double)stotalCount), sumPokey, stotalCount);
net_print_string(NULL, 0, "TIA: max %d, min %d, avg: %f (sum:%llu, count:%llu)\n",
maxTia, minTia, (sumTia/(double)stotalCount), sumTia, stotalCount);
scount = stotalCount = 0;
maxPokey = minPokey = sumPokey = 0;
maxTia = minTia = sumTia = 0;
}
#endif
return true;
}
@ -139,11 +185,8 @@ bool sound_Store( ) {
// ----------------------------------------------------------------------------
// Play
// ----------------------------------------------------------------------------
bool sound_Play( ) {
byte sample[MAX_BUFFER_SIZE];
memset( sample, 0, MAX_BUFFER_SIZE );
wii_storeSound( sample, 1024 );
//ResetAudio();
bool sound_Play( ) {
ResetAudio();
return true;
}
@ -151,10 +194,7 @@ bool sound_Play( ) {
// Stop
// ----------------------------------------------------------------------------
bool sound_Stop( ) {
byte sample[MAX_BUFFER_SIZE];
memset( sample, 0, MAX_BUFFER_SIZE );
wii_storeSound( sample, 1024 );
//StopAudio();
StopAudio();
return true;
}

View file

@ -39,12 +39,20 @@
// Tia.cpp
// ----------------------------------------------------------------------------
#include "Tia.h"
#include <string.h>
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define TIA_POLY4_SIZE 15
#define TIA_POLY5_SIZE 31
#define TIA_POLY9_SIZE 511
byte tia_buffer[TIA_BUFFER_SIZE] = {0};
uint tia_size = 524;
uint tia_size = TIA_BUFFER_SIZE;
static const byte TIA_POLY4[ ] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
static const byte TIA_POLY5[ ] = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1};
@ -119,9 +127,8 @@ void tia_Reset( ) {
// Clear
// ----------------------------------------------------------------------------
void tia_Clear( ) {
for(int index = 0; index < TIA_BUFFER_SIZE; index++) {
tia_buffer[index] = 0;
}
tia_soundCntr = 0;
memset(tia_buffer, 0, TIA_BUFFER_SIZE);
}
// ----------------------------------------------------------------------------

View file

@ -62,7 +62,8 @@ enum NODETYPE {
NODETYPE_SPACER,
NODETYPE_RESUME,
NODETYPE_ADVANCED,
NODETYPE_CARTRIDGE_SAVE_STATES_SPACER,
NODETYPE_CARTRIDGE_SETTINGS,
NODETYPE_CARTRIDGE_SETTINGS_SPACER,
NODETYPE_CARTRIDGE_SAVE_STATES,
NODETYPE_CARTRIDGE_SAVE_STATES_SLOT,
NODETYPE_DEBUG_MODE,
@ -77,11 +78,6 @@ enum NODETYPE {
NODETYPE_MAX_FRAME_RATE,
NODETYPE_DIFF_SWITCH_DISPLAY,
NODETYPE_DIFF_SWITCH_ENABLED,
NODETYPE_SWAP_BUTTONS,
NODETYPE_HIGH_SCORE_MODE,
NODETYPE_CARTRIDGE_SETTINGS,
NODETYPE_CARTRIDGE_WSYNC,
NODETYPE_CARTRIDGE_CYCLE_STEALING,
NODETYPE_DISPLAY_SETTINGS,
NODETYPE_CONTROLS_SETTINGS,
NODETYPE_LIGHTGUN_CROSSHAIR,
@ -93,7 +89,33 @@ enum NODETYPE {
NODETYPE_FILTER,
NODETYPE_GX_VI_SCALER,
NODETYPE_DOUBLE_STRIKE,
NODETYPE_TRAP_FILTER
NODETYPE_TRAP_FILTER,
NODETYPE_CART_SETTINGS_CART_TYPE,
NODETYPE_CART_SETTINGS_REGION,
NODETYPE_CART_SETTINGS_SAVE,
NODETYPE_CART_SETTINGS_DELETE,
NODETYPE_CART_SETTINGS_WSYNC,
NODETYPE_CART_SETTINGS_CYCLE_STEALING,
NODETYPE_CART_SETTINGS_POKEY,
NODETYPE_CART_SETTINGS_XM,
NODETYPE_CART_SETTINGS_DISABLE_BIOS,
NODETYPE_CART_SETTINGS_LEFT_SWITCH,
NODETYPE_CART_SETTINGS_RIGHT_SWITCH,
NODETYPE_CART_SETTINGS_CART_SETTINGS,
NODETYPE_CART_SETTINGS_DIFF_SWITCH_SETTINGS,
NODETYPE_CART_SETTINGS_CONTROLS_SETTINGS,
NODETYPE_CART_SETTINGS_SWAP_BUTTONS,
NODETYPE_CART_SETTINGS_CONTROLLER1,
NODETYPE_CART_SETTINGS_CONTROLLER2,
NODETYPE_CART_SETTINGS_DUAL_ANALOG,
NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_X,
NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_Y,
NODETYPE_CART_SETTINGS_CONTROLS_SPACER,
NODETYPE_CART_SETTINGS_HBLANK,
NODETYPE_CART_SETTINGS_HSC,
NODETYPE_ADVANCED_DIFF_SWITCH_SETTINGS
};
#endif

View file

@ -31,6 +31,7 @@
| |
\*--------------------------------------------------------------------------*/
#include "Cartridge.h"
#include "Database.h"
#include "Sound.h"
#include "Timer.h"
@ -57,6 +58,12 @@
#include "wii_atari_emulation.h"
#include "wii_atari_input.h"
#include "wii_atari_sdl.h"
#include "wii_atari_db.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
// The size of the crosshair
#define CROSSHAIR_SIZE 11
@ -68,7 +75,8 @@
/** The default screen sizes */
static const screen_size default_screen_sizes[] = {
{DEFAULT_SCREEN_X, DEFAULT_SCREEN_Y, "Atari 7800 PAR (6:7)"},
{DEFAULT_SCREEN_X, DEFAULT_SCREEN_Y, "0.857 PAR (6:7)"},
{616, DEFAULT_SCREEN_Y, "0.9625 PAR"},
{640, DEFAULT_SCREEN_Y, "Square Pixels (1:1)"}
};
@ -82,16 +90,6 @@ byte atari_pal8[256] = {0};
BOOL wii_lightgun_flash = TRUE;
/** Whether to display a crosshair for the lightgun */
BOOL wii_lightgun_crosshair = TRUE;
/** Whether wsync is enabled/disabled */
u8 wii_cart_wsync = CART_MODE_AUTO;
/** Whether cycle stealing is enabled/disabled */
u8 wii_cart_cycle_stealing = CART_MODE_AUTO;
/** Whether high score cart is enabled */
BOOL wii_hs_enabled = TRUE;
/** What mode the high score cart is in */
BOOL wii_hs_mode = HSMODE_ENABLED_NORMAL;
/** Whether to swap buttons */
BOOL wii_swap_buttons = FALSE;
/** If the difficulty switches are enabled */
BOOL wii_diff_switch_enabled = FALSE;
/** When to display the difficulty switches */
@ -126,13 +124,15 @@ static bool left_difficulty_down = false;
/** Whether the right difficulty switch is on */
static bool right_difficulty_down = false;
/** The keyboard (controls) data */
static unsigned char keyboard_data[19];
unsigned char keyboard_data[19];
/** The amount of time to wait before reading the difficulty switches */
static int diff_wait_count = 0;
/** The amount of time left to display the difficulty switch values */
static int diff_display_count = 0;
/** The current roms directory */
static char roms_dir[WII_MAX_PATH] = "";
/** The current cartridge title */
char rom_title[WII_MAX_PATH] = "";
/** The saves directory */
static char saves_dir[WII_MAX_PATH] = "";
@ -141,6 +141,10 @@ int wii_ir_x = -100;
/** The y location of the Wiimote (IR) */
int wii_ir_y = -100;
#if 0
float wii_orient_roll = 0;
#endif
// Forward reference
static void wii_atari_display_crosshairs(int x, int y, BOOL erase);
@ -346,12 +350,12 @@ void wii_reset_keyboard_data() {
memset(keyboard_data, 0, sizeof(keyboard_data));
// Left difficulty switch defaults to off
keyboard_data[15] = 1;
keyboard_data[15] = cartridge_left_switch;
left_difficulty_down = false;
// Right difficulty swtich defaults to on
keyboard_data[16] = 0;
right_difficulty_down = true;
// Right difficulty switch defaults to on
keyboard_data[16] = cartridge_right_switch;
right_difficulty_down = false;
diff_wait_count = prosystem_frequency * 0.75;
diff_display_count = 0;
@ -371,8 +375,17 @@ bool wii_atari_load_rom(char* filename, bool loadbios) {
database_Load(cartridge_digest);
// If no title, use the one used during loading the rom
if (cartridge_title.length() == 0) {
cartridge_title = rom_title;
}
// Provide opportunity to capture settings
wii_atari_db_after_load();
bios_enabled = false;
if (loadbios) {
#ifdef ENABLE_BIOS_SUPPORT
if (loadbios && !cartridge_disable_bios) {
char boot_rom[WII_MAX_PATH];
snprintf(boot_rom, WII_MAX_PATH, "%s%s", wii_get_fs_prefix(),
(cartridge_region == REGION_PAL ? WII_ROOT_BOOT_ROM_PAL
@ -384,6 +397,20 @@ bool wii_atari_load_rom(char* filename, bool loadbios) {
bios_enabled = false;
}
}
#endif
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "Final values:\n");
net_print_string(NULL, 0, " xm: %s\n", (cartridge_xm ? "1" : "0"));
net_print_string(NULL, 0, " pokey: %s\n", (cartridge_pokey ? "1" : "0"));
net_print_string(NULL, 0, " pokey450: %s\n", (cartridge_pokey450 ? "1" : "0"));
net_print_string(NULL, 0, " tv type: %s\n", cartridge_region ? "PAL" : "NTSC");
net_print_string(NULL, 0, " controller1: %d\n", cartridge_controller[0]);
net_print_string(NULL, 0, " controller2: %d\n", cartridge_controller[1]);
net_print_string(NULL, 0, " cartridge_type: %d\n", cartridge_type);
net_print_string(NULL, 0, " bios disabled: %s\n", cartridge_disable_bios ? "1" : "0");
net_print_string(NULL, 0, " hsc enabled: %s\n", cartridge_hsc_enabled ? "1" : "0");
#endif
wii_reset_keyboard_data();
wii_atari_init_palette8();
@ -473,10 +500,9 @@ static void wii_atari_display_diff_switches() {
/**
* Refreshes the Wii display
*
* @param sync Whether vsync is available for the current frame
* @param testframes The number of testframes to run (for loading saves)
*/
static void wii_atari_refresh_screen(bool sync, int testframes) {
static void wii_atari_refresh_screen(int testframes) {
if (diff_wait_count > 0) {
// Reduces the number of frames remaining to display the difficulty
// switches.
@ -496,15 +522,6 @@ static void wii_atari_refresh_screen(bool sync, int testframes) {
wii_atari_display_crosshairs(wii_ir_x, wii_ir_y, TRUE);
}
if (sync) {
#if 0
wii_sync_video();
#else
// TODO: Evaluate how to evaluate this
VIDEO_WaitVSync();
#endif
}
if (testframes < 0) {
wii_sdl_flip();
}
@ -561,6 +578,36 @@ static void wii_atari_update_wiimote_ir() {
}
}
#if 0
static void wii_atari_update_wiimote_roll() {
orient_t orient;
WPAD_Orientation( WPAD_CHAN_0, &orient );
wii_orient_roll = orient.roll;
//-60 + 60;
int val = wii_orient_roll;
if (val < -60)
val = -60;
if (val > 60)
val = 60;
val = -val;
// 0 to 120;
val += 60;
float ratio = 140/120.0;//(circus)
//float ratio = 60/120.0; //(ark)
val *= ratio;
val += 40; //(circus)
//val += 20;// (ark)
wii_orient_roll = val;
}
#endif
// The number of cycles per scanline that the 7800 checks for a hit
#define LG_CYCLES_PER_SCANLINE 318
// The number of cycles indented (after HBLANK) prior to checking for a hit
@ -672,13 +719,13 @@ static void wii_atari_update_joystick(int joyIndex,
gcHeld & GC_BUTTON_ATARI_UP || wii_analog_up(expY, gcY) ||
wii_analog_up(expRjsY, gcRjsY));
// | 04 10 | Joystick 1 2 | Button 1
keyboard_data[wii_swap_buttons ? 4 + offset : 5 + offset] =
keyboard_data[cartridge_swap_buttons ? 4 + offset : 5 + offset] =
(held & (WII_BUTTON_ATARI_FIRE |
(isClassic ? WII_CLASSIC_ATARI_FIRE
: WII_NUNCHECK_ATARI_FIRE)) ||
gcHeld & GC_BUTTON_ATARI_FIRE);
// | 05 11 | Joystick 1 2 | Button 2
keyboard_data[wii_swap_buttons ? 5 + offset : 4 + offset] =
keyboard_data[cartridge_swap_buttons ? 5 + offset : 4 + offset] =
(held & (WII_BUTTON_ATARI_FIRE_2 |
(isClassic ? WII_CLASSIC_ATARI_FIRE_2
: WII_NUNCHECK_ATARI_FIRE_2)) ||
@ -748,6 +795,9 @@ static void wii_atari_update_keys(unsigned char keyboard_data[19]) {
if (lightgun_enabled) {
wii_atari_update_wiimote_ir();
}
#if 0
wii_atari_update_wiimote_roll();
#endif
wii_atari_update_joystick(0, keyboard_data);
wii_atari_update_joystick(1, keyboard_data);
}
@ -794,12 +844,17 @@ void wii_render_callback() {
* riot_drb, memory_ram[SWCHB] */
sprintf(text,
"v: %.2f, hs: %d, %d, timer: %d, wsync: %s, %d, stl: %s, "
"mar: %d, cpu: %d, ext: %d, rnd: %d, hb: %d",
"mar: %d, cpu: %d, ext: %d, rnd: %d, hb: %d, db: %s",
wii_fps_counter, high_score_set, hs_sram_write_count,
(riot_timer_count % 1000), (dbg_wsync ? "1" : "0"),
dbg_wsync_count, (dbg_cycle_stealing ? "1" : "0"),
dbg_maria_cycles, dbg_p6502_cycles, dbg_saved_cycles,
RANDOM, cartridge_hblank);
RANDOM, cartridge_hblank,
cart_in_db ? "1" : "0");
#if 0
", roll: %f"
, wii_orient_roll
#endif
}
GXColor color = (GXColor){0x0, 0x0, 0x0, 0x80};
@ -903,7 +958,7 @@ void wii_atari_main_loop(int testframes) {
// Only enable lightgun if the cartridge supports it and we are displaying
// at 2x.
lightgun_enabled =
(cartridge_controller[0] & CARTRIDGE_CONTROLLER_LIGHTGUN);
(cartridge_controller[0] == CARTRIDGE_CONTROLLER_LIGHTGUN);
float fps_counter;
u32 timerCount = 0;
@ -917,6 +972,11 @@ void wii_atari_main_loop(int testframes) {
wii_set_video_mode(TRUE);
wii_gx_push_callback(&wii_render_callback, TRUE, NULL);
}
// Sync up timing prior to launching
VIDEO_WaitVSync();
VIDEO_WaitVSync();
timer_Reset();
while (!prosystem_paused) {
if (testframes < 0) {
@ -929,13 +989,23 @@ void wii_atari_main_loop(int testframes) {
if (prosystem_active && !prosystem_paused) {
prosystem_ExecuteFrame(keyboard_data);
if (wii_vsync) {
#if 0
wii_sync_video();
#else
// TODO: Evaluate how to evaluate this
VIDEO_WaitVSync();
#endif
}
while (!timer_IsTime())
;
fps_counter =
(((float)timerCount++ / (SDL_GetTicks() - start_time)) *
1000.0);
wii_atari_refresh_screen(wii_vsync, testframes);
wii_atari_refresh_screen(testframes);
if (testframes < 0) {
sound_Store();

View file

@ -35,6 +35,7 @@
#define WII_ATARI_H
#include <gctypes.h>
#include "wii_main.h"
#include "wii_resize_screen.h"
// Dimensions of the surface that is being written to
@ -93,16 +94,6 @@ extern bool wii_testframe;
extern BOOL wii_lightgun_flash;
/** Whether to display a crosshair for the lightgun */
extern BOOL wii_lightgun_crosshair;
/** Whether wsync is enabled/disabled */
extern u8 wii_cart_wsync;
/** Whether cycle stealing is enabled/disabled */
extern u8 wii_cart_cycle_stealing;
/** Whether high score cart is enabled */
extern BOOL wii_hs_enabled;
/** What mode the high score cart is in */
extern BOOL wii_hs_mode;
/** Whether to swap buttons */
extern BOOL wii_swap_buttons;
/** Whether the difficulty switches are enabled */
extern BOOL wii_diff_switch_enabled;
/** When to display the difficulty switches */
@ -119,6 +110,8 @@ extern int wii_screen_y;
extern BOOL wii_filter;
/** Whether to use the GX/VI scaler */
extern BOOL wii_gx_vi_scaler;
/** The current cartridge title */
extern char rom_title[WII_MAX_PATH];
/**
* Returns the current roms directory

View file

@ -61,14 +61,6 @@ void wii_config_handle_read_value(char* name, char* value) {
wii_diff_switch_display = Util_sscandec(value);
} else if (strcmp(name, "diff_switch_enabled") == 0) {
wii_diff_switch_enabled = Util_sscandec(value);
} else if (strcmp(name, "swap_buttons") == 0) {
wii_swap_buttons = Util_sscandec(value);
} else if (strcmp(name, "high_score_cart") == 0) {
wii_hs_mode = Util_sscandec(value);
} else if (strcmp(name, "cart_wsync") == 0) {
wii_cart_wsync = Util_sscandec(value);
} else if (strcmp(name, "cart_cycle_stealing") == 0) {
wii_cart_cycle_stealing = Util_sscandec(value);
} else if (strcmp(name, "lightgun_crosshair") == 0) {
wii_lightgun_crosshair = Util_sscandec(value);
} else if (strcmp(name, "lightgun_flash") == 0) {
@ -115,11 +107,7 @@ void wii_config_handle_write_config(FILE* fp) {
fprintf(fp, "top_menu_exit=%d\n", wii_top_menu_exit);
fprintf(fp, "vsync=%d\n", wii_vsync);
fprintf(fp, "diff_switch_display=%d\n", wii_diff_switch_display);
fprintf(fp, "swap_buttons=%d\n", wii_swap_buttons);
fprintf(fp, "diff_switch_enabled=%d\n", wii_diff_switch_enabled);
fprintf(fp, "high_score_cart=%d\n", wii_hs_mode);
fprintf(fp, "cart_wsync=%d\n", wii_cart_wsync);
fprintf(fp, "cart_cycle_stealing=%d\n", wii_cart_cycle_stealing);
fprintf(fp, "lightgun_crosshair=%d\n", wii_lightgun_crosshair);
fprintf(fp, "lightgun_flash=%d\n", wii_lightgun_flash);
fprintf(fp, "screen_x=%d\n", wii_screen_x);

807
src/wii/wii_atari_db.cpp Normal file
View file

@ -0,0 +1,807 @@
/*--------------------------------------------------------------------------*\
| |
| __ __.__.___________ ______ _______ _______ |
| / \ / \__|__\______ \/ __ \\ _ \ \ _ \ |
| \ \/\/ / | | / /> </ /_\ \/ /_\ \ |
| \ /| | | / // -- \ \_/ \ \_/ \ |
| \__/\ / |__|__| /____/ \______ /\_____ /\_____ / |
| \/ \/ \/ \/ |
| |
| Wii7800 by raz0red |
| Wii port of the ProSystem emulator developed by Greg Stanton |
| |
| [github.com/raz0red/wii7800] |
| |
+----------------------------------------------------------------------------+
| |
| 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 2 |
| 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, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301, USA. |
| |
\*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "Cartridge.h"
#include "Region.h"
#include "wii_app_common.h"
#include "wii_app.h"
#include "wii_main.h"
#include "wii_atari_db.h"
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define DB_FILE_PATH WII_PROSYSTEM_DB
#define DB_TMP_FILE_PATH WII_FILES_DIR "ProSystem.dat.tmp"
#define DB_OLD_FILE_PATH WII_FILES_DIR "ProSystem.dat.old"
/**
* Cartridge settings.
*
* For these settings to be applied, the settings must be saved, and the
* cartridge must be re-loaded.
*/
typedef struct CartSettings {
/** The type of cartridge */
byte type;
/** Whether pokey is enabled */
bool pokey;
/** Whether pokey at $450 is enabled */
bool pokey450;
/** The region of the cartridge */
byte region;
/** Flags for the cartridge */
uint flags;
/** Whether the expansion module is enabled */
bool xm;
/** Whether to disable the bios loadig */
bool disable_bios;
/** The hblank */
int hblank;
/** High score cartridge */
bool hsc_enabled;
} CartSettings;
extern unsigned char keyboard_data[19];
/** The database file */
static char db_file[WII_MAX_PATH] = "";
/** The database temp file */
static char db_tmp_file[WII_MAX_PATH] = "";
/** The database old file */
static char db_old_file[WII_MAX_PATH] = "";
/** The cartridge settings */
static CartSettings cart_settings = {0};
/** Whether the cart exists in the DB */
static bool cart_exists_in_db = false;
/**
* This method is invoked after a cartridge has been loaded. It provides an
* opportunity for the current cartridge settings to be captured, so they can be
* viewed and modified later.
*/
void wii_atari_db_after_load()
{
cart_settings.type = cartridge_type;
cart_settings.pokey = cartridge_pokey;
cart_settings.pokey450 = cartridge_pokey450;
cart_settings.region = cartridge_region;
cart_settings.flags = cartridge_flags;
cart_settings.xm = cartridge_xm;
cart_settings.disable_bios = cartridge_disable_bios;
cart_settings.hblank = cartridge_hblank;
cart_settings.hsc_enabled = cartridge_hsc_enabled;
cart_exists_in_db = false;
}
/**
* Returns the path to the database file
*
* @return The path to the database file
*/
static char* get_db_path() {
if (db_file[0] == '\0') {
snprintf(db_file, WII_MAX_PATH, "%s%s", wii_get_fs_prefix(),
DB_FILE_PATH);
}
return db_file;
}
/**
* Returns the path to the database temporary file
*
* @return The path to the database temporary file
*/
static char* get_db_tmp_path() {
if (db_tmp_file[0] == '\0') {
snprintf(db_tmp_file, WII_MAX_PATH, "%s%s", wii_get_fs_prefix(),
DB_TMP_FILE_PATH);
}
return db_tmp_file;
}
/**
* Returns the path to the database old file
*
* @return The path to the database old file
*/
static char* get_db_old_path() {
if (db_old_file[0] == '\0') {
snprintf(db_old_file, WII_MAX_PATH, "%s%s", wii_get_fs_prefix(),
DB_OLD_FILE_PATH);
}
return db_old_file;
}
/**
* Writes the database entry to the specified file
*
* @param file The file to write the entry to
* @param hash The hash for the entry
*/
static void write_entry(FILE* file, const char* hash) {
#ifdef WII_NETTRACE
net_print_string(NULL, 0, "writing db entry with hash: [%s]\n", hash);
#endif
bool lightgun =
cartridge_controller[0] == CARTRIDGE_CONTROLLER_LIGHTGUN ||
cartridge_controller[1] == CARTRIDGE_CONTROLLER_LIGHTGUN;
bool bothJoystick =
cartridge_controller[0] == CARTRIDGE_CONTROLLER_JOYSTICK &&
cartridge_controller[1] == CARTRIDGE_CONTROLLER_JOYSTICK;
fprintf(file, "[%s]\n", hash);
fprintf(file, "title=%s\n", cartridge_title.c_str());
fprintf(file, "type=%d\n", cart_settings.type);
fprintf(file, "pokey=%s\n", cart_settings.pokey ? "true" : "false");
fprintf(file, "controller1=%d\n", cartridge_controller[0]);
fprintf(file, "controller2=%d\n", cartridge_controller[1]);
fprintf(file, "region=%d\n", cart_settings.region);
fprintf(file, "flags=%d\n", cart_settings.flags);
fprintf(file, "pokey450=%s\n", cart_settings.pokey450 ? "true" : "false");
fprintf(file, "xm=%s\n", cart_settings.xm ? "true" : "false");
fprintf(file, "hsc=%s\n", cart_settings.hsc_enabled ? "true" : "false");
if (lightgun) {
if (cartridge_crosshair_x) {
fprintf(file, "crossx=%d\n", cartridge_crosshair_x);
}
if (cartridge_crosshair_y) {
fprintf(file, "crossy=%d\n", cartridge_crosshair_y);
}
}
#ifdef ENABLE_BIOS_SUPPORT
if (cart_settings.disable_bios) {
fprintf(file, "disablebios=%s\n", cart_settings.disable_bios ? "true" : "false");
}
#endif
/*byte cartridge_left_switch = 1;*/ // Default
if (cartridge_left_switch != 1) {
fprintf(file, "leftswitch=%d\n", cartridge_left_switch);
}
/*byte cartridge_right_switch = 0;*/ // Default
if (cartridge_right_switch != 0) {
fprintf(file, "rightswitch=%d\n", cartridge_right_switch);
}
if (cartridge_swap_buttons) {
fprintf(file, "swapbuttons=%s\n", cartridge_swap_buttons ? "true" : "false");
}
if (bothJoystick && cartridge_dualanalog) {
fprintf(file, "dualanalog=%s\n", cartridge_dualanalog ? "true" : "false");
}
if (cart_settings.hblank != HBLANK_DEFAULT) {
fprintf(file, "hblank=%d\n", cart_settings.hblank);
}
}
/**
* Attempts to locate a hash in the specified source string. If it
* is found, it is copied into dest.
*
* @param source The source string
* @param dest The destination string
* @return non-zero if the hash was found and copied
*/
static int get_hash(char* source, char* dest) {
int db_hash_len = 0; // Length of the hash
char* end_idx; // End index of the hash
char* start_idx; // Start index of the hash
start_idx = source;
if (*start_idx == '[') {
++start_idx;
end_idx = strrchr(start_idx, ']');
if (end_idx != 0) {
db_hash_len = end_idx - start_idx;
strncpy(dest, start_idx, db_hash_len);
dest[db_hash_len] = '\0';
return 1;
}
}
return 0;
}
/**
* Attempts to find an entry for the specified hash
*
* @param hash The hash of the game
* @return Whether the entry was found
*/
static bool db_find_entry(const char* hash) {
char buff[255]; // The buffer to use when reading the file
char db_hash[255]; // A hash found in the file we are reading from
// The database file
FILE* db_file = fopen(get_db_path(), "r");
// A database file doesn't exist
if (!db_file) {
return false;
}
bool found = false;
while (!found && fgets(buff, sizeof(buff), db_file) != 0) {
// Check if we found a hash
if (get_hash(buff, db_hash)) {
if (!strcmp(hash, db_hash)) {
found = true;
}
}
}
fclose(db_file);
return found;
}
/**
* Writes the settings for the current game
*
* @param hash The hash of the game
* @param delete Whether to delete the entry
* @return Whether the write was successful
*/
static int db_write_entry(const char* hash, bool del) {
char buff[255]; // The buffer to use when reading the file
char db_hash[255]; // A hash found in the file we are reading from
int copy_mode = 0; // The current copy mode
FILE* tmp_file = 0; // The temp file
FILE* old_file = 0; // The old file
// The database file
FILE* db_file = fopen(get_db_path(), "r");
// A database file doesn't exist, create a new one
if (!db_file && !del) {
db_file = fopen(get_db_path(), "w");
if (!db_file) {
// Unable to create DB file
return 0;
}
// Write the entry
write_entry(db_file, hash);
fclose(db_file);
} else {
//
// A database exists, search for the appropriate hash while copying
// its current contents to a temp file
//
// Open up the temp file
tmp_file = fopen(get_db_tmp_path(), "w");
if (!tmp_file) {
fclose(db_file);
// Unable to create temp file
return 0;
}
//
// Loop and copy
//
while (fgets(buff, sizeof(buff), db_file) != 0) {
// Check if we found a hash
if (copy_mode < 2 && get_hash(buff, db_hash)) {
if (copy_mode) {
copy_mode++;
} else if (!strcmp(hash, db_hash)) {
// We have matching hashes, write out the new entry
if (!del) {
write_entry(tmp_file, hash);
}
copy_mode++;
}
}
if (copy_mode != 1) {
fprintf(tmp_file, "%s", buff);
}
}
if (!copy_mode) {
// We didn't find the hash in the database, add it
if (!del) {
write_entry(tmp_file, hash);
}
}
fclose(db_file);
fclose(tmp_file);
//
// Make sure the temporary file exists
// We do this due to the instability of the Wii SD card
//
tmp_file = fopen(get_db_tmp_path(), "r");
if (!tmp_file) {
// Unable to find temp file
return 0;
}
fclose(tmp_file);
// Delete old file (if it exists)
if ((old_file = fopen(get_db_old_path(), "r")) != 0) {
fclose(old_file);
if (remove(get_db_old_path()) != 0) {
return 0;
}
}
// Rename database file to old file
if (rename(get_db_path(), get_db_old_path()) != 0) {
return 0;
}
// Rename temp file to database file
if (rename(get_db_tmp_path(), get_db_path()) != 0) {
return 0;
}
}
return 1;
}
/**
* Deletes the entry from the database with the specified hash
*
* @param hash The hash of the game
* @return Whether the delete was successful
*/
static int db_delete_entry(const char* hash) {
return db_write_entry(hash, true);
}
/**
* Checks to see if an entry exists in the database for the current game
*
* @return Whether an entry exists in the database for the current game
*/
bool wii_atari_db_check_exists() {
cart_exists_in_db = db_find_entry(cartridge_digest.c_str());
return cart_exists_in_db;
}
/**
* Creates the menu entries for the cartridge settings menu
*/
void wii_atari_db_create_menu(TREENODE* cart_settings_menu) {
//
// Cartridge settings
//
TREENODE* cart_settings = wii_create_tree_node(
NODETYPE_CART_SETTINGS_CART_SETTINGS, "Cartridge settings");
wii_add_child(cart_settings_menu, cart_settings);
TREENODE* child = wii_create_tree_node(NODETYPE_CART_SETTINGS_CART_TYPE, "Cartridge type");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_REGION, "Region");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_POKEY, "Pokey");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_HSC, "High score cartridge (HSC)");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_XM, "Expansion module (XM)");
wii_add_child(cart_settings, child);
#ifdef ENABLE_BIOS_SUPPORT
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_DISABLE_BIOS, "BIOS");
wii_add_child(cart_settings, child);
#endif
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_WSYNC, "Handle WSYNC");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_CYCLE_STEALING, "Cycle stealing");
wii_add_child(cart_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_HBLANK, "HBlank");
wii_add_child(cart_settings, child);
//
// Controls settings
//
TREENODE* controls = wii_create_tree_node(
NODETYPE_CART_SETTINGS_CONTROLS_SETTINGS, "Control settings");
wii_add_child(cart_settings_menu, controls);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_CONTROLLER1,
"Controller 1");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_CONTROLLER2,
"Controller 2");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_SWAP_BUTTONS,
"Swap buttons");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_CONTROLS_SPACER, "");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_DUAL_ANALOG,
"Dual analog");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_X,
"Lightgun offset X");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_Y,
"Lightgun offset Y");
wii_add_child(controls, child);
//
// Difficulty switch settings
//
TREENODE* diff_switch_settings = wii_create_tree_node(
NODETYPE_CART_SETTINGS_DIFF_SWITCH_SETTINGS, "Difficulty switch settings");
wii_add_child(cart_settings_menu, diff_switch_settings);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_LEFT_SWITCH, "Left switch");
wii_add_child(diff_switch_settings, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_RIGHT_SWITCH, "Right switch");
wii_add_child(diff_switch_settings, child);
//
// Save/Delete settings
//
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(cart_settings_menu, child);
child =
wii_create_tree_node(NODETYPE_CART_SETTINGS_SAVE, "Save settings");
wii_add_child(cart_settings_menu, child);
child = wii_create_tree_node(NODETYPE_CART_SETTINGS_DELETE,
"Delete settings");
wii_add_child(cart_settings_menu, child);
}
/**
* Updates the buffer with the name of the specified node
*
* @param node The node
* @param buffer The name of the specified node
* @param value The value of the specified node
*/
void wii_atari_db_get_node_name(TREENODE* node, char* buffer, char* value) {
const char* strmode = "";
switch (node->node_type) {
case NODETYPE_CART_SETTINGS_CART_TYPE:
switch (cart_settings.type) {
case CARTRIDGE_TYPE_NORMAL:
strmode = "Normal";
break;
case CARTRIDGE_TYPE_SUPERCART:
strmode = "SuperGame bank switched";
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
strmode = "SuperGame ROM at $4000 (bank 0)";
break;
case CARTRIDGE_TYPE_SUPERCART_RAM:
strmode = "SuperGame RAM at $4000";
break;
case CARTRIDGE_TYPE_SUPERCART_ROM:
strmode = "SuperGame ROM at $4000 (bank 6)";
break;
case CARTRIDGE_TYPE_ABSOLUTE:
strmode = "Absolute";
break;
case CARTRIDGE_TYPE_ACTIVISION:
strmode = "Activision";
break;
case CARTRIDGE_TYPE_NORMAL_RAM:
strmode="Normal RAM at $4000";
break;
default:
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_CART_SETTINGS_REGION:
switch (cart_settings.region) {
case REGION_NTSC:
strmode = "NTSC";
break;
case REGION_PAL:
strmode = "PAL";
break;
default:
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_CART_SETTINGS_WSYNC:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cart_settings.flags & CARTRIDGE_WSYNC_MASK ? "Disabled" : "Enabled");
break;
case NODETYPE_CART_SETTINGS_CYCLE_STEALING:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cart_settings.flags & CARTRIDGE_CYCLE_STEALING_MASK ? "Disabled" : "Enabled");
break;
case NODETYPE_CART_SETTINGS_XM:
snprintf(value, WII_MENU_BUFF_SIZE, "%s", cart_settings.xm ? "Enabled" : "Disabled");
break;
case NODETYPE_CART_SETTINGS_SWAP_BUTTONS:
snprintf(value, WII_MENU_BUFF_SIZE, "%s", cartridge_swap_buttons ? "Enabled" : "Disabled");
break;
case NODETYPE_CART_SETTINGS_POKEY:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cart_settings.pokey ?
(cart_settings.pokey450 ? "Pokey at $0450" : "Pokey at $4000") :
"Disabled");
break;
case NODETYPE_CART_SETTINGS_DISABLE_BIOS:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cart_settings.disable_bios ? "Disabled" : "Enabled");
break;
case NODETYPE_CART_SETTINGS_HSC:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cart_settings.hsc_enabled ? "Enabled" : "Disabled");
break;
case NODETYPE_CART_SETTINGS_LEFT_SWITCH:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cartridge_left_switch ? "B" : "A");
break;
case NODETYPE_CART_SETTINGS_RIGHT_SWITCH:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cartridge_right_switch ? "B" : "A");
break;
case NODETYPE_CART_SETTINGS_CONTROLLER1:
case NODETYPE_CART_SETTINGS_CONTROLLER2: {
byte controller = cartridge_controller
[node->node_type == NODETYPE_CART_SETTINGS_CONTROLLER1 ? 0 : 1];
const char* ctype = "(Unknown)";
switch (controller) {
case CARTRIDGE_CONTROLLER_JOYSTICK:
ctype = "Joystick";
break;
case CARTRIDGE_CONTROLLER_LIGHTGUN:
ctype = "Lightgun";
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", ctype);
} break;
case NODETYPE_CART_SETTINGS_DUAL_ANALOG:
snprintf(value, WII_MENU_BUFF_SIZE, "%s",
cartridge_dualanalog ? "Enabled" : "Disabled");
break;
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_X:
snprintf(value, WII_MENU_BUFF_SIZE, "%d",
cartridge_crosshair_x);
break;
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_Y:
snprintf(value, WII_MENU_BUFF_SIZE, "%d",
cartridge_crosshair_y);
break;
case NODETYPE_CART_SETTINGS_HBLANK:
snprintf(
value, WII_MENU_BUFF_SIZE, "%d %s", cart_settings.hblank,
(cart_settings.hblank == HBLANK_DEFAULT ? " (default)" : ""));
break;
}
}
/**
* React to the "select" event for the specified node
*
* @param node The node that was selected
*/
void wii_atari_db_select_node(TREENODE* node) {
switch (node->node_type) {
case NODETYPE_CART_SETTINGS_CART_SETTINGS:
case NODETYPE_CART_SETTINGS_DIFF_SWITCH_SETTINGS:
case NODETYPE_CART_SETTINGS_CONTROLS_SETTINGS:
wii_menu_push(node);
break;
case NODETYPE_CART_SETTINGS_CART_TYPE:
cart_settings.type++;
if (cart_settings.type > CARTRIDGE_TYPE_NORMAL_RAM) {
cart_settings.type = 0;
}
wii_set_status_message(
"Type changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_REGION:
cart_settings.region++;
if (cart_settings.region > REGION_PAL) {
cart_settings.region = 0;
}
wii_set_status_message(
"Region changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_WSYNC:
cart_settings.flags ^= CARTRIDGE_WSYNC_MASK;
wii_set_status_message(
"WSYNC changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_CYCLE_STEALING:
cart_settings.flags ^= CARTRIDGE_CYCLE_STEALING_MASK;
wii_set_status_message(
"Cycle stealing changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_POKEY:
if(cart_settings.pokey) {
if (!cart_settings.pokey450) {
cart_settings.pokey450 = true;
} else {
cart_settings.pokey = false;
cart_settings.pokey450 = false;
}
} else {
cart_settings.pokey = true;
}
wii_set_status_message(
"Pokey changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_XM:
cart_settings.xm ^= 1;
wii_set_status_message(
"XM changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_DISABLE_BIOS:
cart_settings.disable_bios ^= 1;
wii_set_status_message(
"BIOS changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_LEFT_SWITCH:
cartridge_left_switch ^= 1;
keyboard_data[15] = cartridge_left_switch;
break;
case NODETYPE_CART_SETTINGS_RIGHT_SWITCH:
cartridge_right_switch ^= 1;
keyboard_data[16] = cartridge_right_switch;
break;
case NODETYPE_CART_SETTINGS_SWAP_BUTTONS:
cartridge_swap_buttons ^= 1;
break;
case NODETYPE_CART_SETTINGS_HSC:
cart_settings.hsc_enabled ^= 1;
wii_set_status_message(
"High score cart changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_CONTROLLER1:
case NODETYPE_CART_SETTINGS_CONTROLLER2: {
byte index =
node->node_type == NODETYPE_CART_SETTINGS_CONTROLLER1 ? 0 : 1;
cartridge_controller[index]++;
if (cartridge_controller[index] > CARTRIDGE_CONTROLLER_LIGHTGUN) {
cartridge_controller[index] = CARTRIDGE_CONTROLLER_JOYSTICK;
}
} break;
case NODETYPE_CART_SETTINGS_DUAL_ANALOG:
cartridge_dualanalog ^= 1;
break;
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_X:
cartridge_crosshair_x++;
if (cartridge_crosshair_x > 20) {
cartridge_crosshair_x = -20;
}
break;
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_Y:
cartridge_crosshair_y++;
if (cartridge_crosshair_y > 20) {
cartridge_crosshair_y = -20;
}
break;
case NODETYPE_CART_SETTINGS_HBLANK:
cart_settings.hblank++;
if (cart_settings.hblank > 50) {
cart_settings.hblank = 0;
}
wii_set_status_message(
"HBlank changes not applied until cartridge is reloaded");
break;
case NODETYPE_CART_SETTINGS_SAVE:
if (db_write_entry(cartridge_digest.c_str(), false)) {
wii_set_status_message(
"Successfully saved cartridge settings.");
} else {
wii_set_status_message(
"An error occurred saving cartridge settings.");
}
wii_atari_db_check_exists();
break;
case NODETYPE_CART_SETTINGS_DELETE:
if (db_delete_entry(cartridge_digest.c_str())) {
wii_menu_reset_indexes();
wii_menu_move(wii_menu_stack[wii_menu_stack_head], 1);
wii_set_status_message(
"Successfully deleted cartridge settings.");
} else {
wii_set_status_message(
"An error occurred deleting cartridge settings.");
}
wii_atari_db_check_exists();
break;
}
}
/**
* Determines whether the node is currently visible
*
* @param node The node
* @return Whether the node is visible
*/
BOOL wii_atari_db_is_node_visible(TREENODE* node) {
switch (node->node_type) {
case NODETYPE_CART_SETTINGS_DELETE:
return cart_exists_in_db;
case NODETYPE_CART_SETTINGS_DUAL_ANALOG:
return cartridge_controller[0] == CARTRIDGE_CONTROLLER_JOYSTICK &&
cartridge_controller[1] == CARTRIDGE_CONTROLLER_JOYSTICK;
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_X:
case NODETYPE_CART_SETTINGS_LIGHTGUN_OFFSET_Y:
return cartridge_controller[0] == CARTRIDGE_CONTROLLER_LIGHTGUN ||
cartridge_controller[1] == CARTRIDGE_CONTROLLER_LIGHTGUN;
case NODETYPE_CART_SETTINGS_CONTROLS_SPACER:
return cartridge_controller[0] != CARTRIDGE_CONTROLLER_JOYSTICK ||
cartridge_controller[1] != CARTRIDGE_CONTROLLER_JOYSTICK;
}
return TRUE;
}
/**
* Determines whether the node is selectable
*
* @param node The node
* @return Whether the node is selectable
*/
BOOL wii_atari_db_is_node_selectable(TREENODE* node) {
return node->node_type != NODETYPE_CART_SETTINGS_CONTROLS_SPACER;
}

91
src/wii/wii_atari_db.h Normal file
View file

@ -0,0 +1,91 @@
/*--------------------------------------------------------------------------*\
| |
| __ __.__.___________ ______ _______ _______ |
| / \ / \__|__\______ \/ __ \\ _ \ \ _ \ |
| \ \/\/ / | | / /> </ /_\ \/ /_\ \ |
| \ /| | | / // -- \ \_/ \ \_/ \ |
| \__/\ / |__|__| /____/ \______ /\_____ /\_____ / |
| \/ \/ \/ \/ |
| |
| Wii7800 by raz0red |
| Wii port of the ProSystem emulator developed by Greg Stanton |
| |
| [github.com/raz0red/wii7800] |
| |
+----------------------------------------------------------------------------+
| |
| 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 2 |
| 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, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301, USA. |
| |
\*--------------------------------------------------------------------------*/
#ifndef WII_ATARI_DB_H
#define WII_ATARI_DB_H
#include "wii_main.h"
/**
* This method is invoked after a cartridge has been loaded. It provides an
* opportunity for the current cartridge settings to be captured, so they can be
* viewed and modified later.
*/
void wii_atari_db_after_load();
/**
* Creates the menu entries for the cartridge settings menu
*/
void wii_atari_db_create_menu(TREENODE* cart_settings_menu);
/**
* Updates the buffer with the name of the specified node
*
* @param node The node
* @param buffer The name of the specified node
* @param value The value of the specified node
*/
void wii_atari_db_get_node_name(TREENODE* node, char* buffer, char* value);
/**
* React to the "select" event for the specified node
*
* @param node The node that was selected
*/
void wii_atari_db_select_node(TREENODE* node);
/**
* Determines whether the node is currently visible
*
* @param node The node
* @return Whether the node is visible
*/
BOOL wii_atari_db_is_node_visible(TREENODE* node);
/**
* Determines whether the node is selectable
*
* @param node The node
* @return Whether the node is selectable
*/
BOOL wii_atari_db_is_node_selectable(TREENODE* node);
/**
* Checks to see if an entry exists in the database for the current game
*
* @return Whether an entry exists in the database for the current game
*/
bool wii_atari_db_check_exists();
#endif

View file

@ -51,6 +51,10 @@ void WII_VideoStart();
void WII_VideoStop();
}
#if 0
extern u32 sound_max;
#endif
/**
* Starts the emulator for the specified rom file.
*
@ -65,9 +69,6 @@ BOOL wii_start_emulation(char* romfile,
const char* savefile,
BOOL reset,
BOOL resume) {
// Disabled the high score cartridge
wii_hs_enabled = (wii_hs_mode != HSMODE_DISABLED);
// Write out the current config
wii_write_config();
@ -80,11 +81,6 @@ BOOL wii_start_emulation(char* romfile,
// Whether to load a save file
loadsave = (savefile != NULL && strlen(savefile) > 0);
// Disable the high score cart for saves if applicable
if (loadsave && (wii_hs_mode != HSMODE_ENABLED_SNAPSHOTS)) {
wii_hs_enabled = false;
}
// If we are not loading a save, reset snapshot related state
// information (current index, etc.)
if (!loadsave) {
@ -124,6 +120,8 @@ BOOL wii_start_emulation(char* romfile,
succeeded = prosystem_Load(savefile);
if (succeeded) {
// Load high score cart after loading saved state
cartridge_LoadHighScoreCart();
wii_atari_pause(false);
} else {
wii_set_status_message(
@ -154,6 +152,11 @@ BOOL wii_start_emulation(char* romfile,
free(old_last);
}
// This was a newly loaded rom, set snapshot index to latest snapshot
if (!loadsave && !reset && !resume) {
wii_snapshot_reset(TRUE);
}
if (wii_max_frame_rate != 0) {
prosystem_frequency = wii_max_frame_rate;
}
@ -165,6 +168,10 @@ BOOL wii_start_emulation(char* romfile,
// Wait until no buttons are pressed
wii_wait_until_no_buttons(2);
#if 0
sound_max = 0;
#endif
wii_atari_main_loop();
if (wii_top_menu_exit) {

View file

@ -35,6 +35,7 @@
#include <stdlib.h>
#include <sys/iosupport.h>
#include "Cartridge.h"
#include "Region.h"
#include "wii_app_common.h"
@ -52,6 +53,7 @@
#include "wii_atari.h"
#include "wii_atari_emulation.h"
#include "wii_atari_snapshot.h"
#include "wii_atari_db.h"
#include "gettext.h"
@ -123,14 +125,14 @@ void wii_atari_menu_init() {
roms_menu = child;
wii_add_child(wii_menu_root, child);
child =
wii_create_tree_node(NODETYPE_CARTRIDGE_SETTINGS_SPACER, "");
wii_add_child(wii_menu_root, child);
//
// Save state management
//
child =
wii_create_tree_node(NODETYPE_CARTRIDGE_SAVE_STATES_SPACER, "");
wii_add_child(wii_menu_root, child);
TREENODE* states =
wii_create_tree_node(NODETYPE_CARTRIDGE_SAVE_STATES, "Save states");
wii_add_child(wii_menu_root, states);
@ -150,6 +152,17 @@ void wii_atari_menu_init() {
child = wii_create_tree_node(NODETYPE_DELETE_STATE, "Delete state");
wii_add_child(states, child);
//
// Cartridge settings
//
TREENODE* cart_settings =
wii_create_tree_node(NODETYPE_CARTRIDGE_SETTINGS, "Cartridge-specific settings");
wii_add_child(wii_menu_root, cart_settings);
// Add items to the cart settings menu
wii_atari_db_create_menu(cart_settings);
//
// The advanced menu
//
@ -208,23 +221,6 @@ void wii_atari_menu_init() {
wii_create_tree_node(NODETYPE_CONTROLS_SETTINGS, "Control settings");
wii_add_child(advanced, controls);
child = wii_create_tree_node(NODETYPE_SWAP_BUTTONS, "Swap buttons");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(controls, child);
child =
wii_create_tree_node(NODETYPE_DIFF_SWITCH_ENABLED, "Diff. switches");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_DIFF_SWITCH_DISPLAY,
"Diff. switches display");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(controls, child);
child = wii_create_tree_node(NODETYPE_LIGHTGUN_CROSSHAIR,
"Lightgun crosshair");
wii_add_child(controls, child);
@ -233,25 +229,21 @@ void wii_atari_menu_init() {
wii_add_child(controls, child);
//
// The cartridge settings menu
// The diff switch settings
//
TREENODE* cartridge =
wii_create_tree_node(NODETYPE_CARTRIDGE_SETTINGS, "Cartridge settings");
wii_add_child(advanced, cartridge);
TREENODE* diffswitch =
wii_create_tree_node(NODETYPE_ADVANCED_DIFF_SWITCH_SETTINGS, "Difficulty switch settings");
wii_add_child(advanced, diffswitch);
child = wii_create_tree_node(NODETYPE_HIGH_SCORE_MODE, "High score cart.");
wii_add_child(cartridge, child);
child =
wii_create_tree_node(NODETYPE_DIFF_SWITCH_ENABLED, "Diff. Switch buttons");
wii_add_child(diffswitch, child);
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(cartridge, child);
child = wii_create_tree_node(NODETYPE_DIFF_SWITCH_DISPLAY,
"Display switches");
wii_add_child(diffswitch, child);
child = wii_create_tree_node(NODETYPE_CARTRIDGE_WSYNC, "Handle WSYNC");
wii_add_child(cartridge, child);
child = wii_create_tree_node(NODETYPE_CARTRIDGE_CYCLE_STEALING,
"Cycle stealing");
wii_add_child(cartridge, child);
child = wii_create_tree_node(NODETYPE_SPACER, "");
wii_add_child(advanced, child);
@ -425,52 +417,6 @@ void wii_menu_handle_get_node_name(TREENODE* node, char* buffer, char* value) {
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_HIGH_SCORE_MODE:
switch (wii_hs_mode) {
case HSMODE_ENABLED_NORMAL:
strmode = "Enabled (excludes saved state)";
break;
case HSMODE_ENABLED_SNAPSHOTS:
strmode = "Enabled (includes saved state)";
break;
case HSMODE_DISABLED:
strmode = "Disabled";
break;
default:
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_CARTRIDGE_WSYNC:
switch (wii_cart_wsync) {
case CART_MODE_AUTO:
strmode = "(auto)";
break;
case CART_MODE_ENABLED:
strmode = "Enabled";
break;
case CART_MODE_DISABLED:
strmode = "Disabled";
break;
default:
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_CARTRIDGE_CYCLE_STEALING:
switch (wii_cart_cycle_stealing) {
case CART_MODE_AUTO:
strmode = "(auto)";
break;
case CART_MODE_ENABLED:
strmode = "Enabled";
break;
case CART_MODE_DISABLED:
strmode = "Disabled";
break;
}
snprintf(value, WII_MENU_BUFF_SIZE, "%s", strmode);
break;
case NODETYPE_MAX_FRAME_RATE:
if (wii_max_frame_rate == 0) {
snprintf(value, WII_MENU_BUFF_SIZE, "(auto)");
@ -480,7 +426,6 @@ void wii_menu_handle_get_node_name(TREENODE* node, char* buffer, char* value) {
break;
case NODETYPE_DEBUG_MODE:
case NODETYPE_TOP_MENU_EXIT:
case NODETYPE_SWAP_BUTTONS:
case NODETYPE_DIFF_SWITCH_ENABLED:
case NODETYPE_LIGHTGUN_CROSSHAIR:
case NODETYPE_LIGHTGUN_FLASH:
@ -504,9 +449,6 @@ void wii_menu_handle_get_node_name(TREENODE* node, char* buffer, char* value) {
case NODETYPE_TOP_MENU_EXIT:
enabled = wii_top_menu_exit;
break;
case NODETYPE_SWAP_BUTTONS:
enabled = wii_swap_buttons;
break;
case NODETYPE_DIFF_SWITCH_ENABLED:
enabled = wii_diff_switch_enabled;
break;
@ -527,6 +469,8 @@ void wii_menu_handle_get_node_name(TREENODE* node, char* buffer, char* value) {
default:
break;
}
wii_atari_db_get_node_name(node, buffer, value);
}
/**
@ -548,6 +492,9 @@ void wii_menu_handle_select_node(TREENODE* node) {
case NODETYPE_ROM:
snprintf(buff, sizeof(buff), "%s%s",
wii_get_roms_dir(), node->name);
// Default the cartridge title
rom_title[0] = '\0';
snprintf(rom_title, WII_MAX_PATH, "%s", node->name);
last_rom_index = wii_menu_get_current_index();
loading_game = TRUE;
wii_start_emulation(buff);
@ -575,6 +522,9 @@ void wii_menu_handle_select_node(TREENODE* node) {
} else {
LOCK_RENDER_MUTEX();
// Allow DB to select node
wii_atari_db_select_node(node);
switch (node->node_type) {
case NODETYPE_ROOT_DRIVE:
case NODETYPE_UPDIR:
@ -645,24 +595,6 @@ void wii_menu_handle_select_node(TREENODE* node) {
wii_diff_switch_display = 0;
}
break;
case NODETYPE_CARTRIDGE_CYCLE_STEALING:
wii_cart_cycle_stealing++;
if (wii_cart_cycle_stealing > 2) {
wii_cart_cycle_stealing = 0;
}
break;
case NODETYPE_CARTRIDGE_WSYNC:
wii_cart_wsync++;
if (wii_cart_wsync > 2) {
wii_cart_wsync = 0;
}
break;
case NODETYPE_HIGH_SCORE_MODE:
wii_hs_mode++;
if (wii_hs_mode > 2) {
wii_hs_mode = 0;
}
break;
case NODETYPE_VSYNC:
wii_set_vsync(wii_vsync ^ 1);
break;
@ -701,15 +633,15 @@ void wii_menu_handle_select_node(TREENODE* node) {
case NODETYPE_WIIMOTE_MENU_ORIENT:
wii_mote_menu_vertical ^= 1;
break;
case NODETYPE_SWAP_BUTTONS:
wii_swap_buttons ^= 1;
break;
case NODETYPE_DIFF_SWITCH_ENABLED:
wii_diff_switch_enabled ^= 1;
break;
case NODETYPE_CARTRIDGE_SETTINGS:
wii_atari_db_check_exists();
wii_menu_push(node);
break;
case NODETYPE_ADVANCED:
case NODETYPE_LOAD_ROM:
case NODETYPE_CARTRIDGE_SETTINGS:
case NODETYPE_LOAD_ROM:
case NODETYPE_DISPLAY_SETTINGS:
case NODETYPE_CONTROLS_SETTINGS:
wii_menu_push(node);
@ -735,6 +667,9 @@ void wii_menu_handle_select_node(TREENODE* node) {
}
}
break;
case NODETYPE_ADVANCED_DIFF_SWITCH_SETTINGS:
wii_menu_push(node);
break;
default:
break;
}
@ -760,7 +695,8 @@ BOOL wii_menu_handle_is_node_visible(TREENODE* node) {
return !wii_gx_vi_scaler && !wii_double_strike_mode;
case NODETYPE_RESET:
case NODETYPE_RESUME:
case NODETYPE_CARTRIDGE_SAVE_STATES_SPACER:
case NODETYPE_CARTRIDGE_SETTINGS_SPACER:
case NODETYPE_CARTRIDGE_SETTINGS:
case NODETYPE_CARTRIDGE_SAVE_STATES:
return wii_last_rom != NULL;
break;
@ -768,6 +704,10 @@ BOOL wii_menu_handle_is_node_visible(TREENODE* node) {
break;
}
if (!wii_atari_db_is_node_visible(node)) {
return FALSE;
}
return TRUE;
}
@ -778,9 +718,14 @@ BOOL wii_menu_handle_is_node_visible(TREENODE* node) {
* @return Whether the node is selectable
*/
BOOL wii_menu_handle_is_node_selectable(TREENODE* node) {
if (node->node_type == NODETYPE_CARTRIDGE_SAVE_STATES_SPACER) {
if (node->node_type == NODETYPE_CARTRIDGE_SETTINGS_SPACER) {
return FALSE;
}
if (!wii_atari_db_is_node_selectable(node)) {
return FALSE;
}
return TRUE;
}

View file

@ -13,13 +13,18 @@
#include <gccore.h>
#include <string.h>
#ifdef WII_NETTRACE
#include <network.h>
#include "net_print.h"
#endif
#define SAMPLERATE 48000
#define MIXBUFSIZE_BYTES 32000 // 16000
#define MIXBUFSIZE_BYTES (64*1024) // 32000 16000
#define MIXBUFSIZE_SHORT (MIXBUFSIZE_BYTES / 2)
#define MIXBUFSIZE_WORDS (MIXBUFSIZE_BYTES / 4)
#define SOUNDBUFSIZE 4096 // 2048
#define SOUNDBUFSIZE (64*1024) // 4096 2048
static u8 soundbuffer[2][SOUNDBUFSIZE] ATTRIBUTE_ALIGN(32);
static u8 mixbuffer[MIXBUFSIZE_BYTES];
@ -73,6 +78,7 @@ static void AudioSwitchBuffers() {
DCFlushRange(soundbuffer[whichab], len);
AUDIO_InitDMA((u32)soundbuffer[whichab], len);
AUDIO_StartDMA();
whichab ^= 1;
IsPlaying = 1;
}
@ -118,13 +124,14 @@ void ResetAudio() {
* Puts incoming mono samples into mixbuffer
* Splits mono samples into two channels (stereo)
****************************************************************************/
void PlaySound(u8* Buffer, int count) {
u32* dst = (u32*)mixbuffer;
int i;
u16 sample;
for (i = 0; i < count; i++) {
sample = ((Buffer[i] << 8) - 1) & 0xffff;
sample = ((Buffer[i] << 8) /*- 1*/) & 0xff00;
dst[mixhead++] = sample | (sample << 16);
if (mixhead == MIXBUFSIZE_WORDS)
mixhead = 0;

@ -1 +1 @@
Subproject commit 5d1b8867e6e8c574d6f0ac54a75ebcdbbdb4d199
Subproject commit 126294c6db505e72474a9a55ef6c2a5f72830801