Compare commits

..

No commits in common. "master" and "1.29" have entirely different histories.
master ... 1.29

30 changed files with 2276 additions and 3303 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 574 B

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 574 B

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View file

@ -1,6 +0,0 @@
Background: #000000
InactiveItem: #461F99
ActiveItem: #FFFFFF
MessageText: #461F99
InactiveMain: #FFFFFF
ActiveMain: #FFFFFF

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,7 @@ C_SOURCES = source/unzip/explode.c source/unzip/unreduce.c \
source/unzip/unshrink.c source/unzip/unzip.c \ source/unzip/unshrink.c source/unzip/unzip.c \
source/nds/bdf_font.c source/nds/bitmap.c \ source/nds/bdf_font.c source/nds/bitmap.c \
source/nds/draw.c source/nds/ds2_main.c source/nds/gcheat.c \ source/nds/draw.c source/nds/ds2_main.c source/nds/gcheat.c \
source/nds/gui.c source/nds/dma_adj.c source/nds/cheatgrp.c source/nds/gui.c source/nds/dma_adj.c
CPP_SOURCES = source/apu.cpp source/apudebug.cpp source/c4.cpp \ CPP_SOURCES = source/apu.cpp source/apudebug.cpp source/c4.cpp \
source/c4emu.cpp source/cheats2.cpp source/cheats.cpp \ source/c4emu.cpp source/cheats2.cpp source/cheats.cpp \
source/clip.cpp source/cpu.cpp source/cpuexec.cpp \ source/clip.cpp source/cpu.cpp source/cpuexec.cpp \

149
README.md
View file

@ -1,4 +1,4 @@
CATSFC version 1.36, 2013-06-16 CATSFC version 1.29, 2013-02-08
A Super Nintendo emulator for the Supercard DSTWO. A Super Nintendo emulator for the Supercard DSTWO.
@ -7,22 +7,55 @@ Based on:
zsKnight, etc.) zsKnight, etc.)
* NDSSFC 1.06, by the Supercard team (porting to the MIPS processor) * NDSSFC 1.06, by the Supercard team (porting to the MIPS processor)
* BAGSFC, by BassAceGold (improving over NDSSFC) * BAGSFC, by BassAceGold (improving over NDSSFC)
* CATSFC, by ShadauxCat and Nebuleon (improving over BAGSFC) * CATSFC, by ShadauxCat (improving over BAGSFC)
Contains: # Compiling
* Language files written by the GBAtemp community: Dutch by Aeter, French
by Nebuleon, German by SignZ, Portuguese (Brazilian) by Diego Liberal, (If you downloaded the plugin ready-made, you can safely skip this section.
Spanish by Boriar In this case, go to `# Installing`.)
* Language files written by GitHub users: Italian by alexinfurs
Compiling CATSFC is best done on Linux. Make sure you have access to a Linux
system to perform these steps.
## The DS2 SDK
To compile CATSFC, you need to have the Supercard team's DS2 SDK.
The Makefile expects it at `/opt/ds2sdk`, but you can move it anywhere,
provided that you update the Makefile's `DS2SDKPATH` variable to point to it.
For best results, download version 0.13 of the DS2 SDK, which will have the
MIPS compiler (`gcc`), extract it to `/opt/ds2sdk`, follow the instructions,
then download version 1.2 of the DS2 SDK and extract its files into
`opt/ds2sdk`, overwriting version 0.13.
Additionally, you will need to add the updated `zlib`, DMA
(Direct Memory Access) and filesystem access routines provided by BassAceGold
and recompile `libds2a.a`. To do this:
> sudo rm -r /opt/ds2sdk/libsrc/{console,core,fs,key,zlib,Makefile} /opt/ds2sdk/include
> sudo cp -r sdk-modifications/{libsrc,include} /opt/ds2sdk
> sudo chmod -R 600 /opt/ds2sdk/{libsrc,include}
> sudo chmod -R a+rX /opt/ds2sdk/{libsrc,include}
> cd /opt/ds2sdk/libsrc
> sudo rm libds2a.a ../lib/libds2a.a
> sudo make
## The MIPS compiler (`gcc`)
You also need the MIPS compiler from the DS2 SDK.
The Makefile expects it at `/opt/mipsel-4.1.2-nopic`, but you can move it
anywhere, provided that you update the Makefile's `CROSS` variable to point to
it.
## Making the plugin
To make the plugin, `catsfc.plg`, use the `cd` command to change to the
directory containing your copy of the CATSFC source, then type
`make clean; make`. `catsfc.plg` should appear in the same directory.
# Installing # Installing
(If you got the source code and want to compile it, see the `Compiling` section To install the plugin to your storage card after compiling it, copy
at the end of the file.) `catsfc.plg`, `catsfc.ini` and `catsfc.bmp` to the card's `_dstwoplug`
directory. Then, copy the source directory's CATSFC subdirectory to the
To install the plugin to your storage card, copy `catsfc.plg`, `catsfc.ini` and root of the card.
`catsfc.bmp` from the release archive to the card's `_dstwoplug` directory.
Then, copy the `CATSFC` subdirectory to the root of the card.
# Cheats # Cheats
@ -35,9 +68,14 @@ old format used in Mightymo's BSNES Cheat Code Pack.
the operating system on your computer. the operating system on your computer.
3. In the zip file, open the folder called *BSNES Cheat Code Pack*, then 3. In the zip file, open the folder called *BSNES Cheat Code Pack*, then
the one called *BSNES v0.51-0.74 Cheat Code Pack*. the one called *BSNES v0.51-0.74 Cheat Code Pack*.
4. Open your storage card's CATSFC folder, then descend into gamecht. 4. Open your microSD card's CATSFC folder, then descend into gamecht.
5. Drag the cheat code files from the zip archive to the card's gamecht 5. Drag the cheat code files from the zip archive to the card's gamecht
folder. folder.
6. In the card's gamecht directory, create two folders. Name the first one
*a-m* and the second one *n-z*. Drag the cheat files from the games whose
name starts with A to M into *a-m* and the rest into *n-z*.
This is because the directory display does not handle more than 512 files.
To add cheats to the menu in a game, first load the game, then use the Cheats To add cheats to the menu in a game, first load the game, then use the Cheats
menu's "Load a cheat file" option. menu's "Load a cheat file" option.
@ -59,7 +97,7 @@ For some games, you may need to adjust frame skipping.
* If you want to show more frames per second in a game that already shows 20, * If you want to show more frames per second in a game that already shows 20,
setting frame skipping to 1 or 0 will cause more frames to appear, setting frame skipping to 1 or 0 will cause more frames to appear,
but your DS button input may stop responding for 2 entire seconds every so but your DS button input may stop responding for 2 entire seconds every so
often. The audio may also be stretched. (This is similar to NDSGBA.) often. The audio will also be stretched. (This is similar to NDSGBA.)
* Setting this to 10 will skip 10 frames and render one, but this will * Setting this to 10 will skip 10 frames and render one, but this will
severely desynchronise the audio. You will also find yourself unable to severely desynchronise the audio. You will also find yourself unable to
perform actions during the correct frame with the DS buttons. It is advised perform actions during the correct frame with the DS buttons. It is advised
@ -105,18 +143,10 @@ Available actions are:
will be forced on. will be forced on.
* Toggle sound. Each time this hotkey is held, the sound will be disabled if * Toggle sound. Each time this hotkey is held, the sound will be disabled if
it's currently enabled, and vice-versa. it's currently enabled, and vice-versa.
* Save state #1. Each time this hotkey is held, saved state #1 will be written,
without confirmation if it exists.
* Load state #1. Each time this hotkey is held, saved state #1 will be loaded.
* Toggle full-screen. Each time this hotkey is held:
* If the current display mode *is* a full-screen mode, then the display mode
is set to 3 (Middle, square pixels) and the top and bottom will be cut off.
* If the current display mode *is not* a full-screen mode, then the display
mode is set to 4 (Entire screen, smoothed).
# The font # The font
The font used by CATSFC is similar to the Pictochat font. To modify it, The font used by CATSFC is now similar to the Pictochat font. To modify it,
see `source/font/README.txt`. see `source/font/README.txt`.
# Translations # Translations
@ -128,87 +158,40 @@ need to do the following:
* Open `CATSFC/system/language.msg`. * Open `CATSFC/system/language.msg`.
* Copy what's between `STARTENGLISH` and `ENDENGLISH` and paste it at the end * Copy what's between `STARTENGLISH` and `ENDENGLISH` and paste it at the end
of the file. of the file.
* Change the tags. For example, if you want to translate to Japanese, the tags * Change the tags. For example, if you want to translate to German, the tags
will become `STARTJAPANESE` and `ENDJAPANESE`. will become `STARTGERMAN` and `ENDGERMAN`.
* Translate each of the messages, using the lines starting with `#MSG_` as a * Translate each of the messages, using the lines starting with `#MSG_` as a
guide to the context in which the messages will be used. guide to the context in which the messages will be used.
If you are not comfortable editing C code, or cannot compile CATSFC after your
changes, you may instead test your translation in the English block and submit
it. That allows you to look for message length issues and to align the option
names and values to your liking with spaces.
If you wish to also hook your language into the user interface, you will need
to do the following:
* Edit `source/nds/message.h`. Find `enum LANGUAGE` and add the name of your * Edit `source/nds/message.h`. Find `enum LANGUAGE` and add the name of your
language there. For the example of Japanese, you would add this at the end of language there. For the example of German, you would add this at the end of
the list: the list:
``` ```
, ,
JAPANESE GERMAN
``` ```
* Still in `source/nds/message.h`, just below `enum LANGUAGE`, you will find * Still in `source/nds/message.h`, just below `enum LANGUAGE`, you will find
`extern char* lang[` *some number* `]`. Add 1 to that number. `extern char* lang[` *some number* `]`. Add 1 to that number.
* Edit `source/nds/gui.c`. Find `char *lang[` *some number* `] =`. * Edit `source/nds/gui.c`. Find `char *lang[` *some number* `] =`.
Add the name of your language, in the language itself. For the example of Add the name of your language, in the language itself. For the example of
Japanese, you would add this at the end of the list: German, you would add this at the end of the list:
``` ```
, ,
"日本語" "Deutsch"
``` ```
* Still in `source/nds/gui.c`, find `char* language_options[]`, which is below * Still in `source/nds/gui.c`, find `char* language_options[]`, which is below
the language names. Add an entry similar to the others, with the last number the language names. Add an entry similar to the others, with the last number
plus 1. For example, if the last entry is `, (char *) &lang[7]`, yours would plus 1. For example, if the last entry is `, (char *) &lang[2]`, yours would
be `, (char *) &lang[8]`. be `, (char *) &lang[3]`.
* Still in `source/nds/gui.c`, find `case CHINESE_SIMPLIFIED`. Copy the lines * Still in `source/nds/gui.c`, find `case CHINESE_SIMPLIFIED`. Copy the lines
starting at the `case` and ending with `break`, inclusively. Paste them starting at the `case` and ending with `break`, inclusively. Paste them
before the `}`. Change the language name and tags. For the example of before the `}`. Change the language name and tags. For the example of
Japanese, you would use: German, you would use:
``` ```
case JAPANESE: case GERMAN:
strcpy(start, "STARTJAPANESE"); strcpy(start, "STARTGERMAN");
strcpy(end, "ENDJAPANESE"); strcpy(end, "ENDGERMAN");
break; break;
``` ```
Compile again, copy the plugin and your new `language.msg` to your card Compile again, copy the plugin and your new `language.msg` to your card
under `CATSFC/system`, and you can now select your new language in CATSFC! under `CATSFC/system`, and you can now select your new language in CATSFC!
# Compiling
Compiling CATSFC is best done on Linux. Make sure you have access to a Linux
system to perform these steps.
## The DS2 SDK
To compile CATSFC, you need to have the Supercard team's DS2 SDK.
The Makefile expects it at `/opt/ds2sdk`, but you can move it anywhere,
provided that you update the Makefile's `DS2SDKPATH` variable to point to it.
For best results, download version 0.13 of the DS2 SDK, which will have the
MIPS compiler (`gcc`), extract it to `/opt/ds2sdk`, follow the instructions,
then download version 1.2 of the DS2 SDK and extract its files into
`opt/ds2sdk`, overwriting version 0.13.
Additionally, you will need to add the updated `zlib`, DMA
(Direct Memory Access) and filesystem access routines provided by BassAceGold
and recompile `libds2a.a`. To do this:
> sudo rm -r /opt/ds2sdk/libsrc/{console,core,fs,key,zlib,Makefile} /opt/ds2sdk/include
> sudo cp -r sdk-modifications/{libsrc,include} /opt/ds2sdk
> sudo chmod -R 600 /opt/ds2sdk/{libsrc,include}
> sudo chmod -R a+rX /opt/ds2sdk/{libsrc,include}
> cd /opt/ds2sdk/libsrc
> sudo rm libds2a.a ../lib/libds2a.a
> sudo make
## The MIPS compiler (`gcc`)
You also need the MIPS compiler from the DS2 SDK.
The Makefile expects it at `/opt/mipsel-4.1.2-nopic`, but you can move it
anywhere, provided that you update the Makefile's `CROSS` variable to point to
it.
## Making the plugin
To make the plugin, `catsfc.plg`, use the `cd` command to change to the
directory containing your copy of the CATSFC source, then type
`make clean; make`. `catsfc.plg` should appear in the same directory.

View file

@ -1,29 +1,37 @@
#ifndef __DS2_TYPES_H__ #ifndef __DS2_TYPES_H__
#define __DS2_TYPES_H__ #define __DS2_TYPES_H__
typedef unsigned char u8; #ifndef u8
typedef char s8; #define u8 unsigned char
#endif
typedef unsigned short u16; #ifndef s8
typedef short s16; #define s8 char
#endif
typedef unsigned int u32; #ifndef u16
typedef int s32; #define u16 unsigned short
#endif
typedef unsigned long long u64; #ifndef s16
typedef long long s64; #define s16 short
#endif
typedef volatile unsigned char vu8; #ifndef u32
typedef volatile char vs8; #define u32 unsigned int
#endif
typedef volatile unsigned short vu16; #ifndef s32
typedef volatile short vs16; #define s32 int
#endif
typedef volatile unsigned int vu32; #ifndef u64
typedef volatile int vs32; #define u64 unsigned long long
#endif
typedef volatile unsigned long long vu64; #ifndef s64
typedef volatile long long vs64; #define s64 long long
#endif
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0

View file

@ -49,10 +49,9 @@
#define BYTES_PER_READ 512 #define BYTES_PER_READ 512
// MODIFICATION START [Neb] #ifndef NULL
// In libfat by Chishm, some types are #define'd here. In the DS2 SDK, #define NULL 0
// these types are defined by another header. #endif
#include "ds2_types.h"
#ifndef bool #ifndef bool
#define bool int #define bool int
@ -66,7 +65,21 @@
#define true 1 #define true 1
#endif #endif
// MODIFICATION END [Neb] #ifndef u8
#define u8 unsigned char
#endif
#ifndef u16
#define u16 unsigned short
#endif
#ifndef u32
#define u32 unsigned long
#endif
#ifndef s32
#define s32 long
#endif
struct _reent struct _reent
{ {

View file

@ -135,7 +135,7 @@ bool _FAT_directory_isValidLfn (const char* name) {
return true; return true;
} }
bool _FAT_directory_isValidAlias (const char* name) { bool _FAT_directory_isValidAlias (const char* name) {
//return false;//disables this function to preserve file name casing return false;//disables this function to preserve file name casing
u32 i; u32 i;
u32 nameLength; u32 nameLength;
@ -159,7 +159,7 @@ bool _FAT_directory_isValidAlias (const char* name) {
// Make sure the name doesn't contain any control codes // Make sure the name doesn't contain any control codes
//if name isn't all capitals, then it is not a valid short name //if name isn't all capitals, then it is not a valid short name
for (i = 0; i < nameLength; i++) { for (i = 0; i < nameLength; i++) {
if (name[i] > 0x5A && name[i]!= 0x20) { if (name[i] < 0x5A && name[i]!=0x20) {
return false; return false;
} }
} }
@ -756,37 +756,7 @@ static bool _FAT_directory_entryExists (PARTITION* partition, const char* name,
return false; return false;
} }
//a fix for checking if a short file name is already in use.
static bool _FAT_directory_entryExistsSFN (PARTITION* partition, const char* name, u32 dirCluster) {
DIR_ENTRY tempEntry;
bool foundFile;
char alias[MAX_ALIAS_LENGTH];
u32 dirnameLength;
dirnameLength = strnlen(name, MAX_FILENAME_LENGTH);
if (dirnameLength >= MAX_FILENAME_LENGTH) {
return false;
}
// Make sure the entry doesn't already exist
foundFile = _FAT_directory_getFirstEntry (partition, &tempEntry, dirCluster);
while (foundFile) { // It hasn't already found the file
if(!strcasecmp(name, tempEntry.d_name))
return true;
// Check if the alias matches
_FAT_directory_entryGetAlias (tempEntry.entryData, alias);
if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH))
&& (strcasecmp(alias, name) == 0)) {
return true;
}
foundFile = _FAT_directory_getNextEntry (partition, &tempEntry);
}
return false;
}
bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) { bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirCluster) {
u32 entrySize; u32 entrySize;
@ -863,7 +833,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu
++ j; ++ j;
} }
// Short filename // Short filename
strupr (entry->entryData); strupr (entry->d_name);
}else { }else {
// Long filename needed // Long filename needed
//memset( entry->unicodeFilename, 0, 512 ); //memset( entry->unicodeFilename, 0, 512 );
@ -913,7 +883,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu
i++; i++;
alias[6] = '0' + ((i / 10) % 10); // 10's digit alias[6] = '0' + ((i / 10) % 10); // 10's digit
alias[7] = '0' + (i % 10); // 1's digit alias[7] = '0' + (i % 10); // 1's digit
} while (_FAT_directory_entryExistsSFN (partition, alias, dirCluster) && (i < 100)); } while (_FAT_directory_entryExists (partition, alias, dirCluster) && (i < 100));
if (i == 100) { if (i == 100) {
// Couldn't get a tail number // Couldn't get a tail number
return false; return false;

View file

@ -49,10 +49,9 @@
#define BYTES_PER_READ 512 #define BYTES_PER_READ 512
// MODIFICATION START [Neb] #ifndef NULL
// In libfat by Chishm, some types are #define'd here. In the DS2 SDK, #define NULL 0
// these types are defined by another header. #endif
#include "ds2_types.h"
#ifndef bool #ifndef bool
#define bool int #define bool int
@ -66,7 +65,21 @@
#define true 1 #define true 1
#endif #endif
// MODIFICATION END [Neb] #ifndef u8
#define u8 unsigned char
#endif
#ifndef u16
#define u16 unsigned short
#endif
#ifndef u32
#define u32 unsigned long
#endif
#ifndef s32
#define s32 long
#endif
struct _reent struct _reent
{ {

View file

@ -101,7 +101,8 @@ struct SCheat
uint32 address; uint32 address;
uint8 byte; uint8 byte;
uint8 saved_byte; uint8 saved_byte;
bool8 enabled; // bool8 enabled;
u32 enabled; // THIS IS A TOTAL HACK FOR THE NDSSFC GUI, YOU HAVE BEEN WARNED [Neb]
bool8 saved; bool8 saved;
char name[MAX_SFCCHEAT_NAME]; char name[MAX_SFCCHEAT_NAME];
}; };

Binary file not shown.

View file

@ -1022,14 +1022,14 @@ u32 BDF_cut_string(char *string, u32 width, u32 direction)
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
- count UNICODE charactor numbers in width pixels - count UNICODE charactor numbers in width pixels
- direction 0: count UNICODE charactor numbers in width pixels, from end - direction 0: count UNICODE charactor numbers in width pixels, from front
- direction 1: count UNICODE charactor numbers in width pixels, from front - direction 1: count UNICODE charactor numbers in width pixels, from end
- direction 2: conut total pixel width of len UNICODE charachtors, from end - direction 2: conut total pixel width of len UNICODE charachtors, from end
- direction 3: conut total pixel width of len UNICODE charachtors, from front - direction 3: conut total pixel width of len UNICODE charachtors, from front
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction) u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
{ {
u32 i, lastSpace = 0, xw, num; u32 i, xw, num;
u16 unicode; u16 unicode;
u32 start, end; u32 start, end;
struct bdffont *bdf_fontp[2]; struct bdffont *bdf_fontp[2];
@ -1049,19 +1049,14 @@ u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
while(len > 0) while(len > 0)
{ {
unicode= unicodes[i]; unicode= unicodes[i];
if (unicode == 0x0A)
return num - len;
else if (unicode == ' ')
lastSpace = len;
xw += BDF_width16_ucs(unicode); xw += BDF_width16_ucs(unicode);
if(xw > width) return num - lastSpace; if(xw >= width) break;
i += direction; i += direction;
len--; len--;
} }
return num - len; num -= len;
} }
else else
{ {
@ -1078,9 +1073,9 @@ u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
} }
num= xw; num= xw;
return num;
} }
return num;
} }

View file

@ -20,7 +20,6 @@
#include "fs_api.h" #include "fs_api.h"
#include "bitmap.h" #include "bitmap.h"
#include "ds2_malloc.h"
int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height, unsigned int* type) int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height, unsigned int* type)
{ {
@ -60,22 +59,16 @@ int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height,
bmp_header.bfImghead.imColnum= st[23] | (st[24]<<16); bmp_header.bfImghead.imColnum= st[23] | (st[24]<<16);
bmp_header.bfImghead.imImcolnum= st[25] | (st[26]<<16); bmp_header.bfImghead.imImcolnum= st[25] | (st[26]<<16);
if(bmp_header.bfType != 0x4D42) { //"BM" if(bmp_header.bfType != 0x4D42) //"BM"
fclose(fp);
return BMP_ERR_FORMATE; return BMP_ERR_FORMATE;
}
if(bmp_header.bfImghead.imCompess != BI_RGB && if(bmp_header.bfImghead.imCompess != BI_RGB &&
bmp_header.bfImghead.imCompess != BI_BITFIELDS) { bmp_header.bfImghead.imCompess != BI_BITFIELDS)
fclose(fp);
return BMP_ERR_NEED_GO_ON; //This funciton now not support... return BMP_ERR_NEED_GO_ON; //This funciton now not support...
}
bytepixel= bmp_header.bfImghead.imBitpixel >> 3; bytepixel= bmp_header.bfImghead.imBitpixel >> 3;
if(bytepixel < 2) { //byte per pixel >= 2 if(bytepixel < 2) //byte per pixel >= 2
fclose(fp);
return BMP_ERR_NEED_GO_ON; //This funciton now not support... return BMP_ERR_NEED_GO_ON; //This funciton now not support...
}
*type = bytepixel; *type = bytepixel;
@ -88,29 +81,16 @@ int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height,
if(y > sy) if(y > sy)
y= sy; y= sy;
// Expect a certain amount of bytes and read them all at once. //BMP scan from down to up
unsigned int BytesPerLine = (sx * bytepixel + 3) & ~3; fpos= (s32)bmp_header.bfImgoffst;
char* FileBuffer = (char*) malloc(BytesPerLine * (sy - 1) + sx * bytepixel); dest= (unsigned char*)buf+(y-1)*x*bytepixel;
if (FileBuffer == NULL) { for(m= 0; m < y; m++) {
fclose(fp); fseek(fp, fpos, SEEK_SET);
return BMP_ERR_NEED_GO_ON; // Memory allocation error fread(dest, 1, x*bytepixel, fp);
fpos += ((sx*bytepixel+3)>>2)<<2;
dest -= x*bytepixel;
} }
fseek(fp, (s32) bmp_header.bfImgoffst, SEEK_SET);
m = fread(FileBuffer, 1, BytesPerLine * (sy - 1) + sx * bytepixel, fp);
if (m < BytesPerLine * (sy - 1) + sx * bytepixel) {
free(FileBuffer);
fclose(fp);
return BMP_ERR_FORMATE; // incomplete file
}
// Reorder all the bytes, because scanlines are from bottom to top.
for (m = 0; m < y; m++) {
memcpy(buf + m * x * bytepixel, FileBuffer + (sy - m - 1) * BytesPerLine, x * bytepixel);
}
free(FileBuffer);
fclose(fp); fclose(fp);
return BMP_OK; return BMP_OK;

View file

@ -1,100 +0,0 @@
/* cheatgrp.c
*
* Copyright (C) 2013 GBAtemp user Nebuleon.
*
* 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 "cheatgrp.h"
#include "string.h"
#include "ds2_malloc.h"
extern struct SCheatData Cheat;
/*
* Obtains the names of cheat groups currently defined in the Snes9x cheat
* data.
* Cheats are grouped by name, because multipart codes share the same name
* when loaded.
* This function only handles consecutive codes with the same name. If two
* runs of codes have the same name, two identically-named groups will be
* written. Enabling or disabling either of these groups will also enable
* or disable the other if using NDSSFCEnableCheatGroup or
* NDSSFCDisableCheatGroup.
* OUT: NamePointers, an array of MAX_CHEATS_T + 1 pointers which are updated
* by this function. All pointers beyond the last group name are updated
* to point to NULL.
* NameMemory, an array of MAX_CHEATS_T * MAX_SFCCHEAT_NAME char values
* which is updated to hold the names of the groups.
*/
void NDSSFCGetCheatGroups (char** NamePointers, char* NameMemory)
{
unsigned int NameIndex = 0, cheat;
char* dst = NameMemory;
for (cheat = 0; cheat < Cheat.num_cheats; cheat++)
{
if (cheat == 0 || strcmp(Cheat.c [cheat].name, Cheat.c [cheat - 1].name) != 0)
{
memcpy(dst, Cheat.c [cheat].name, MAX_SFCCHEAT_NAME * sizeof (char));
NamePointers[NameIndex] = dst;
dst += MAX_SFCCHEAT_NAME;
NameIndex++;
}
}
for (; NameIndex < MAX_CHEATS_T + 1; NameIndex++)
{
NamePointers[NameIndex] = NULL;
}
}
void NDSSFCEnableCheatGroup (char* GroupName)
{
uint32 cheat;
for (cheat = 0; cheat < Cheat.num_cheats; cheat++)
{
if (strcmp(Cheat.c [cheat].name, GroupName) == 0)
{
S9xEnableCheat (cheat);
}
}
}
void NDSSFCDisableCheatGroup (char* GroupName)
{
uint32 cheat;
for (cheat = 0; cheat < Cheat.num_cheats; cheat++)
{
if (strcmp(Cheat.c [cheat].name, GroupName) == 0)
{
S9xDisableCheat (cheat);
}
}
}
bool8 NDSSFCIsCheatGroupEnabled (char* GroupName)
{
bool8 NameFound = FALSE;
uint32 cheat;
for (cheat = 0; cheat < Cheat.num_cheats; cheat++)
{
if (strcmp(Cheat.c [cheat].name, GroupName) == 0)
{
if (!Cheat.c [cheat].enabled)
return FALSE;
NameFound = TRUE;
}
}
return NameFound;
}

View file

@ -1,27 +0,0 @@
/* cheatgrp.h
*
* Copyright (C) 2013 GBAtemp user Nebuleon.
*
* 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 "port.h"
#include "cheats.h"
extern void NDSSFCGetCheatGroups (char** NamePointers, char* NameMemory);
extern void NDSSFCEnableCheatGroup (char* GroupName);
extern void NDSSFCDisableCheatGroup (char* GroupName);
extern bool8 NDSSFCIsCheatGroupEnabled (char* GroupName);

View file

@ -56,10 +56,10 @@ static uint16 SevenToSixScanlineResize (uint16 TopColour, uint16 BottomColour, u
; ;
} }
void NDSSFCDrawFrameAntialiased (void* screen_addr) void NDSSFCDrawFrameAntialiased ()
{ {
uint16 X, Y; uint16 X, Y;
uint16 *SrcTop = (uint16 *) GFX.Screen, *SrcBottom = SrcTop + 256, *Dest = (uint16 *) screen_addr; uint16 *SrcTop = (uint16 *) GFX.Screen, *SrcBottom = SrcTop + 256, *Dest = (uint16 *) up_screen_addr;
for (Y = 0; Y < 224; Y += 7) for (Y = 0; Y < 224; Y += 7)
{ {

View file

@ -58,6 +58,10 @@
#define GUI_SOURCE_PATH "SYSTEM/GUI" #define GUI_SOURCE_PATH "SYSTEM/GUI"
#define GUI_PIC_BUFSIZE 1024*512 #define GUI_PIC_BUFSIZE 1024*512
u32 screen_height = 272;//160;
u32 screen_width2 = 256/2;
u32 screen_height2 = 160 / 2;
char gui_picture[GUI_PIC_BUFSIZE]; char gui_picture[GUI_PIC_BUFSIZE];
struct gui_iconlist gui_icon_list[]= { struct gui_iconlist gui_icon_list[]= {
@ -106,13 +110,6 @@ struct gui_iconlist gui_icon_list[]= {
/* 34 */ {"sbutto", 76, 16, NULL} /* 34 */ {"sbutto", 76, 16, NULL}
}; };
u16 COLOR_BG = COLOR16( 0, 0, 0);
u16 COLOR_INACTIVE_ITEM = COLOR16( 0, 0, 0);
u16 COLOR_ACTIVE_ITEM = COLOR16(31, 31, 31);
u16 COLOR_MSSG = COLOR16( 0, 0, 0);
u16 COLOR_INACTIVE_MAIN = COLOR16(31, 31, 31);
u16 COLOR_ACTIVE_MAIN = COLOR16(31, 31, 31);
/* /*
* Drawing string aroud center * Drawing string aroud center
@ -305,7 +302,7 @@ void draw_message(void* screen_addr, u16 *screen_bg, u32 sx, u32 sy, u32 ex, u32
{ {
// drawbox(screen_addr, sx, sy, ex, ey, COLOR16(12, 12, 12)); // drawbox(screen_addr, sx, sy, ex, ey, COLOR16(12, 12, 12));
// drawboxfill(screen_addr, sx+1, sy+1, ex-1, ey-1, color_fg); // drawboxfill(screen_addr, sx+1, sy+1, ex-1, ey-1, color_fg);
show_icon(screen_addr, &ICON_MSG, (NDS_SCREEN_WIDTH - ICON_MSG.x) / 2, (NDS_SCREEN_HEIGHT - ICON_MSG.y) / 2); show_icon(screen_addr, &ICON_MSG, 34, 48);
} }
else else
{ {
@ -351,27 +348,29 @@ void draw_string_vcenter(void* screen_addr, u32 sx, u32 sy, u32 width, u32 color
while(*string) while(*string)
{ {
string= utf8decode(string, unicode+num); string= utf8decode(string, unicode+num);
num++; if(unicode[num] != 0x0D && unicode[num] != 0x0A) num++;
} }
if(num== 0) return; if(num== 0) return;
i= BDF_cut_unicode(unicode, num, width, 1);
if(i == num)
{
x= BDF_cut_unicode(unicode, num, 0, 3);
sx += (width - x)/2;
}
screenp = (unsigned short*)screen_addr + sx + sy*SCREEN_WIDTH; screenp = (unsigned short*)screen_addr + sx + sy*SCREEN_WIDTH;
i= 0; i= 0;
while(i < num) while(i < num)
{ {
m= BDF_cut_unicode(&unicode[i], num-i, width, 1); m= BDF_cut_unicode(&unicode[i], num-i, width, 1);
x= (width - BDF_cut_unicode(&unicode[i], m, 0, 3)) / 2; x= 0;
while(m--) while(m--)
{ {
x += BDF_render16_ucs(screenp+x, SCREEN_WIDTH, 0, COLOR_TRANS, x += BDF_render16_ucs(screenp+x, SCREEN_WIDTH, 0, COLOR_TRANS,
color_fg, unicode[i++]); color_fg, unicode[i++]);
} }
if (i < num && (unicode[i] == 0x0D || unicode[i] == 0x0A))
i++;
else {
while (i < num && (unicode[i] == ' ')) i++;
}
screenp += FONTS_HEIGHT * SCREEN_WIDTH; screenp += FONTS_HEIGHT * SCREEN_WIDTH;
} }
} }
@ -409,29 +408,12 @@ struct scroll_string_info{
static struct scroll_string_info scroll_strinfo[MAX_SCROLL_STRING]; static struct scroll_string_info scroll_strinfo[MAX_SCROLL_STRING];
static u32 scroll_string_num= 0; static u32 scroll_string_num= 0;
/* u32 draw_hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
* Initialises a text scroller to display a certain string.
* Input assertions: sx + width < NDS_SCREEN_WIDTH &&
* sy + [text height] < NDS_SCREEN_HEIGHT && string != NULL &&
* screen_addr != NULL.
* Input: 'screen_addr', the address of the upper-left corner of the screen.
* 'sx' and 'sy', the X and Y coordinates of the upper-left corner of
* the text.
* 'width', the width of the scroller's viewport.
* 'color_bg', the RGB15 color of the background around the text, or
* COLOR_TRANS for transparency.
* 'color_fg', the RGB15 color of the text.
* 'string', the text to be scrolled, encoded as UTF-8.
* Output: the scroller's handle, to be used to scroll the text in
* draw_hscroll.
*/
u32 hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
u32 color_bg, u32 color_fg, char *string) u32 color_bg, u32 color_fg, char *string)
{ {
u32 index, x, textWidth, num, len, i; u32 index, x, num, len, i;
u16 *unicode, *screenp; u16 *unicode, *screenp;
// 1. Which scroller should we use for this request?
for(i= 0; i < MAX_SCROLL_STRING; i++) for(i= 0; i < MAX_SCROLL_STRING; i++)
{ {
if(scroll_strinfo[i].screenp == NULL) if(scroll_strinfo[i].screenp == NULL)
@ -442,39 +424,23 @@ u32 hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
return -1; return -1;
index= i; index= i;
screenp= (u16*)malloc((256+128)*FONTS_HEIGHT*2);
// 2. Convert to Unicode while calculating the width of the text.
unicode= (u16*)malloc(strlen(string)*sizeof(u16));
if(unicode == NULL)
{
scroll_strinfo[index].str_len = 0;
return -3;
}
num= 0;
textWidth = 0;
while(*string)
{
string= utf8decode(string, unicode+num);
if(unicode[num] != 0x0D && unicode[num] != 0x0A) {
textWidth += BDF_width16_ucs(unicode[num]);
num++;
}
}
if (textWidth < width)
textWidth = width;
// 3. Allocate a rectangle of pixels for drawing the entire text into.
screenp= (u16*)malloc(textWidth*FONTS_HEIGHT*sizeof(u16));
if(screenp == NULL) if(screenp == NULL)
{ {
scroll_strinfo[index].str_len = 0; scroll_strinfo[index].str_len = 0;
free((void*)unicode);
return -2; return -2;
} }
unicode= (u16*)malloc(256*2);
if(unicode == NULL)
{
scroll_strinfo[index].str_len = 0;
free((void*)screenp);
return -3;
}
if(color_bg == COLOR_TRANS) if(color_bg == COLOR_TRANS)
memset(screenp, 0, textWidth*FONTS_HEIGHT*sizeof(u16)); memset(screenp, 0, (256+128)*FONTS_HEIGHT*2);
scroll_string_num += 1; scroll_string_num += 1;
scroll_strinfo[index].screenp = (unsigned short*)screen_addr; scroll_strinfo[index].screenp = (unsigned short*)screen_addr;
@ -487,81 +453,208 @@ u32 hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
scroll_strinfo[index].unicode= unicode; scroll_strinfo[index].unicode= unicode;
scroll_strinfo[index].buff_fonts= screenp; scroll_strinfo[index].buff_fonts= screenp;
scroll_strinfo[index].buff_bg= 0; scroll_strinfo[index].buff_bg= 0;
scroll_strinfo[index].buff_width= textWidth;
num= 0;
while(*string)
{
string= utf8decode(string, unicode+num);
if(unicode[num] != 0x0D && unicode[num] != 0x0A) num++;
}
scroll_strinfo[index].str_len= num;
if(num == 0)
return index;
len= BDF_cut_unicode(unicode, num, 256+128, 1);
i= 0;
x= 0;
while(i < len)
{
x += BDF_render16_ucs(screenp + x, 256+128, 0, color_bg, color_fg, unicode[i++]);
}
scroll_strinfo[index].buff_width= x;
scroll_strinfo[index].pos_pixel= 0; scroll_strinfo[index].pos_pixel= 0;
scroll_strinfo[index].str_start= 0; scroll_strinfo[index].str_start= 0;
scroll_strinfo[index].str_end= len-1; scroll_strinfo[index].str_end= len-1;
scroll_strinfo[index].str_len= num; num= scroll_strinfo[index].height;
if(num == 0) len= width;
return index; // (1. Which scroller?)
// 4. Render text into the allocation. u16 *screenp1;
i= 0;
x= 0; if(color_bg == COLOR_TRANS)
while(i < num)
{ {
x += BDF_render16_ucs(screenp + x, textWidth, 0, color_bg, color_fg, unicode[i++]); u16 pixel;
for(i= 0; i < num; i++)
{
screenp= (unsigned short*)screen_addr + sx + (sy + i) * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts + i*(256+128);
for(x= 0; x < len; x++)
{
pixel= *screenp1++;
if(pixel) *screenp = pixel;
screenp ++;
}
}
}
else
{
screenp= (unsigned short*)screen_addr + sx + sy * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts;
for(i= 0; i < num; i++)
{
memcpy((char*)screenp, (char*)screenp1, len*2);
screenp += SCREEN_WIDTH;
screenp1 += (256+128);
}
} }
return index; // (1. Which scroller?) return index;
} }
u32 draw_hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
u32 color_bg, u32 color_fg, char *string)
{
u32 ret = hscroll_init(screen_addr, sx, sy, width, color_bg, color_fg, string);
draw_hscroll(ret, 0 /* stay on the left */);
return ret;
}
/*
* Scrolls an initialised scroller's text.
* A scroller is never allowed to go past the beginning of the text when
* scrolling to the left, or to go past the end when scrolling to the right.
* Input assertions: index was returned by a previous call to
* draw_hscroll_init and not used in a call to draw_hscroll_over.
* Input: 'index', the scroller's handle.
* 'scroll_val', the number of pixels to scroll. The sign affects the
* direction. If scroll_val > 0, the scroller's viewport is moved to
* the left; if < 0, the scroller's viewport is moved to the right.
* Output: the number of pixels still available to scroll in the direction
* specified by the sign of 'scroll_val'.
*
* Example: (assume each letter is 1 pixel; this won't be true in reality)
* [some lengthy text shown in ] |
* val -5 -> | [lengthy text shown in a scr]xxxxx -> to right, returns 5
* val -5 -> | [hy text shown in a scroller] -> to right, returns 0
* val 3 -> xxxxxxx[ngthy text shown in a scrol] | -> to left, returns 7
* val 3 -> xxxx[ lengthy text shown in a sc] | -> to left, returns 4
*/
u32 draw_hscroll(u32 index, s32 scroll_val) u32 draw_hscroll(u32 index, s32 scroll_val)
{ {
u32 color_bg, color_fg, i, width, height; u32 color_bg, color_fg, i, width, height;
s32 xoff; s32 xoff;
//static int flag= 0;
if(index >= MAX_SCROLL_STRING) return -1; if(index >= MAX_SCROLL_STRING) return -1;
if(scroll_strinfo[index].screenp == NULL) return -2; if(scroll_strinfo[index].screenp == NULL) return -2;
if(scroll_strinfo[index].str_len == 0) return 0; if(scroll_strinfo[index].str_len == 0) return 0;
width= scroll_strinfo[index].width; width= scroll_strinfo[index].width;
height= scroll_strinfo[index].height; height= scroll_strinfo[index].height;
xoff= scroll_strinfo[index].pos_pixel - scroll_val;
color_bg= scroll_strinfo[index].color_bg; color_bg= scroll_strinfo[index].color_bg;
color_fg= scroll_strinfo[index].color_fg; color_fg= scroll_strinfo[index].color_fg;
// 1. Shift the scroller. if(scroll_val > 0) //shift right
scroll_strinfo[index].pos_pixel -= scroll_val; {
if (scroll_strinfo[index].pos_pixel < 0) // Reached the beginning if(xoff <= 0)
scroll_strinfo[index].pos_pixel = 0; {
else if (scroll_strinfo[index].pos_pixel > scroll_strinfo[index].buff_width - width) // Reached the end if(scroll_strinfo[index].str_start > 0)
scroll_strinfo[index].pos_pixel = scroll_strinfo[index].buff_width - width; {
u32 x, y, len;
u16 *unicode;
u32 *ptr;
//we assume the malloced memory are 4 bytes aligned, or else this method is wrong
y= height*width;
ptr= (u32*)scroll_strinfo[index].buff_fonts;
y= ((256+128)*FONTS_HEIGHT*2+3)/4;
x= 0;
while(x<y) ptr[x++] = 0;
unicode= scroll_strinfo[index].unicode + scroll_strinfo[index].str_end;
len= scroll_strinfo[index].str_end +1;
x= (scroll_val > SCREEN_WIDTH/4) ? scroll_val : SCREEN_WIDTH/4;
y= BDF_cut_unicode(unicode, len, x, 0);
if(y < len) y += 1;
if(y < scroll_strinfo[index].str_start)
scroll_strinfo[index].str_start -= y;
else
{
y= scroll_strinfo[index].str_start;
scroll_strinfo[index].str_start = 0;
}
len= scroll_strinfo[index].str_len - scroll_strinfo[index].str_start;
unicode= scroll_strinfo[index].unicode + scroll_strinfo[index].str_start;
x= 0;
i= 0;
while(i < y)
{
x += BDF_render16_ucs(scroll_strinfo[index].buff_fonts + x, 256+128, 0,
color_bg, color_fg, unicode[i++]);
if(x >= (256+128-14)) break;
}
y= x;
while(i < len)
{
x += BDF_render16_ucs(scroll_strinfo[index].buff_fonts + x, 256+128, 0,
color_bg, color_fg, unicode[i++]);
if(x >= (256+128-14)) break;
}
scroll_strinfo[index].pos_pixel += y - scroll_val;
if((scroll_strinfo[index].pos_pixel + width) > (256+128))
scroll_strinfo[index].pos_pixel= 0;
scroll_strinfo[index].buff_width= x;
scroll_strinfo[index].str_end = scroll_strinfo[index].str_start + i -1;
}
else
{
if(scroll_strinfo[index].pos_pixel > 0)
scroll_strinfo[index].pos_pixel= 0;
else
return 0;
}
xoff= scroll_strinfo[index].pos_pixel;
}
else
scroll_strinfo[index].pos_pixel= xoff;
}
else if(xoff < (s32)scroll_strinfo[index].buff_width) //shift left
{
if((scroll_strinfo[index].buff_width + width) > (256+128))
if((xoff + width) > scroll_strinfo[index].buff_width)
{
u32 x, y, len;
u16 *unicode;
u32 *ptr;
//we assume the malloced memory are 4 bytes aligned, or else this method is wrong
y= height*width;
ptr= (u32*)scroll_strinfo[index].buff_fonts;
y= ((256+128)*FONTS_HEIGHT*2+3)/4;
x= 0;
while(x<y) ptr[x++] = 0;
unicode= scroll_strinfo[index].unicode + scroll_strinfo[index].str_start;
len= scroll_strinfo[index].str_len - scroll_strinfo[index].str_start;
x= (scroll_val > SCREEN_WIDTH/4) ? scroll_val : SCREEN_WIDTH/4;
x= ((s32)x < xoff) ? x : xoff;
y= BDF_cut_unicode(unicode, len, x, 1);
scroll_strinfo[index].str_start += y;
len= scroll_strinfo[index].str_len - scroll_strinfo[index].str_start;
y= scroll_strinfo[index].str_end - scroll_strinfo[index].str_start +1;
unicode= scroll_strinfo[index].unicode + scroll_strinfo[index].str_start;
x= 0;
i= 0;
while(i < y)
{
x += BDF_render16_ucs(scroll_strinfo[index].buff_fonts + x, 256+128, 0,
color_bg, color_fg, unicode[i++]);
}
xoff -= scroll_strinfo[index].buff_width - x;
while(i < len)
{
x += BDF_render16_ucs(scroll_strinfo[index].buff_fonts + x, 256+128, 0,
color_bg, color_fg, unicode[i++]);
if(x >= (256+128-14)) break;
}
scroll_strinfo[index].buff_width= x;
scroll_strinfo[index].str_end = scroll_strinfo[index].str_start + i -1;
}
scroll_strinfo[index].pos_pixel= xoff;
}
else
return 0;
// 2. Draw the scroller's text at its new position.
u32 x, sx, sy, pixel; u32 x, sx, sy, pixel;
u16 *screenp, *screenp1; u16 *screenp, *screenp1;
color_bg = scroll_strinfo[index].color_bg;
sx= scroll_strinfo[index].sx; sx= scroll_strinfo[index].sx;
sy= scroll_strinfo[index].sy; sy= scroll_strinfo[index].sy;
@ -570,7 +663,7 @@ u32 draw_hscroll(u32 index, s32 scroll_val)
for(i= 0; i < height; i++) for(i= 0; i < height; i++)
{ {
screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH; screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts + scroll_strinfo[index].pos_pixel + i*scroll_strinfo[index].buff_width; screenp1= scroll_strinfo[index].buff_fonts + xoff + i*(256+128);
for(x= 0; x < width; x++) for(x= 0; x < width; x++)
{ {
pixel= *screenp1++; pixel= *screenp1++;
@ -584,21 +677,19 @@ u32 draw_hscroll(u32 index, s32 scroll_val)
for(i= 0; i < height; i++) for(i= 0; i < height; i++)
{ {
screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH; screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts + scroll_strinfo[index].pos_pixel + i*scroll_strinfo[index].buff_width; screenp1= scroll_strinfo[index].buff_fonts + xoff + i*(256+128);
for(x= 0; x < width; x++) for(x= 0; x < width; x++)
*screenp++ = *screenp1++; *screenp++ = *screenp1++;
} }
} }
// 3. Return how many more pixels we can scroll in the same direction. u32 ret;
if(scroll_val > 0) if(scroll_val > 0)
// Scrolling to the left: Return the number of pixels we can still go ret= scroll_strinfo[index].pos_pixel;
// to the left.
return scroll_strinfo[index].pos_pixel;
else else
// Scrolling to the right: Return the number of pixels we can still go ret= scroll_strinfo[index].buff_width - scroll_strinfo[index].pos_pixel;
// to the right.
return scroll_strinfo[index].buff_width - scroll_strinfo[index].pos_pixel - width; return ret;
} }
void draw_hscroll_over(u32 index) void draw_hscroll_over(u32 index)
@ -628,7 +719,6 @@ void draw_hscroll_over(u32 index)
/* /*
* Drawing dialog * Drawing dialog
*/ */
/*
void draw_dialog(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey) void draw_dialog(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey)
{ {
drawboxfill(screen_addr, sx + 5, sy + 5, ex + 5, ey + 5, COLOR_DIALOG_SHADOW); drawboxfill(screen_addr, sx + 5, sy + 5, ex + 5, ey + 5, COLOR_DIALOG_SHADOW);
@ -655,7 +745,6 @@ void draw_dialog(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey)
drawboxfill(screen_addr, sx, sy, ex, ey, COLOR_DIALOG); drawboxfill(screen_addr, sx, sy, ex, ey, COLOR_DIALOG);
} }
*/
/* /*
* Draw yes or no dialog * Draw yes or no dialog
@ -702,16 +791,13 @@ u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no)
else else
screen_addr = down_screen_addr; screen_addr = down_screen_addr;
sy = (NDS_SCREEN_HEIGHT + ICON_MSG.y) / 2 - 8 - ICON_BUTTON.y; i= SCREEN_WIDTH/2 - box_width - 2;
show_icon((unsigned short*)screen_addr, &ICON_BUTTON, 49, 128);
draw_string_vcenter((unsigned short*)screen_addr, 51, 130, 73, COLOR_WHITE, yes);
u32 left_sx = NDS_SCREEN_WIDTH / 2 - 8 - ICON_BUTTON.x, i= SCREEN_WIDTH/2 + 3;
right_sx = NDS_SCREEN_WIDTH / 2 + 8; show_icon((unsigned short*)screen_addr, &ICON_BUTTON, 136, 128);
draw_string_vcenter((unsigned short*)screen_addr, 138, 130, 73, COLOR_WHITE, no);
show_icon((unsigned short*)screen_addr, &ICON_BUTTON, left_sx, sy);
draw_string_vcenter((unsigned short*)screen_addr, left_sx + 2, sy, ICON_BUTTON.x - 4, COLOR_WHITE, yes);
show_icon((unsigned short*)screen_addr, &ICON_BUTTON, right_sx, sy);
draw_string_vcenter((unsigned short*)screen_addr, right_sx + 2, sy, ICON_BUTTON.x - 4, COLOR_WHITE, no);
ds2_flipScreen(screen, 2); ds2_flipScreen(screen, 2);
@ -724,11 +810,11 @@ u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no)
struct key_buf inputdata; struct key_buf inputdata;
ds2_getrawInput(&inputdata); ds2_getrawInput(&inputdata);
// Turn it into a SELECT (A) or BACK (B) if the button is touched. // Turn it into a SELECT (A) or BACK (B) if the button is touched.
if (inputdata.y >= sy && inputdata.y < sy + ICON_BUTTON.y) if (inputdata.y >= 128 && inputdata.y < 128 + ICON_BUTTON.y)
{ {
if (inputdata.x >= left_sx && inputdata.x < left_sx + ICON_BUTTON.x) if (inputdata.x >= 49 && inputdata.x < 49 + ICON_BUTTON.x)
gui_action = CURSOR_SELECT; gui_action = CURSOR_SELECT;
else if (inputdata.x >= right_sx && inputdata.x < right_sx + ICON_BUTTON.x) else if (inputdata.x >= 136 && inputdata.x < 136 + ICON_BUTTON.x)
gui_action = CURSOR_BACK; gui_action = CURSOR_BACK;
} }
} }
@ -812,11 +898,12 @@ u32 draw_hotkey_dialog(enum SCREEN_ID screen, u32 sy, char *clear, char *cancel)
// Now, while there are keys pressed, keep a tally of keys that have // Now, while there are keys pressed, keep a tally of keys that have
// been pressed. (IGNORE TOUCH AND LID! Otherwise, closing the lid or // been pressed. (IGNORE TOUCH AND LID! Otherwise, closing the lid or
// touching to get to the menu will do stuff the user doesn't expect.) // touching to get to the menu will do stuff the user doesn't expect.
// Also ignore the direction pad because every game uses it.)
u32 TotalKeys = 0; u32 TotalKeys = 0;
do { do {
TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID); TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID | KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT);
// If there's a touch on either button, turn it into a // If there's a touch on either button, turn it into a
// clear (A) or cancel (B) request. // clear (A) or cancel (B) request.
if (inputdata.key & KEY_TOUCH) if (inputdata.key & KEY_TOUCH)
@ -836,6 +923,93 @@ u32 draw_hotkey_dialog(enum SCREEN_ID screen, u32 sy, char *clear, char *cancel)
return TotalKeys; return TotalKeys;
} }
/*
* Drawing progress bar
*/
static enum SCREEN_ID _progress_screen_id;
static int progress_total;
static int progress_current;
static char progress_message[256];
// progress bar initialize
void init_progress(enum SCREEN_ID screen, u32 total, char *text)
{
void* screen_addr;
_progress_screen_id = screen;
if(_progress_screen_id & UP_MASK)
screen_addr = up_screen_addr;
else
screen_addr = down_screen_addr;
progress_current = 0;
progress_total = total;
// strcpy(progress_message, text);
// draw_dialog(progress_sx - 8, progress_sy -29, progress_ex + 8, progress_ey + 13);
// boxfill(progress_sx - 1, progress_sy - 1, progress_ex + 1, progress_ey + 1, 0);
// if (text[0] != '\0')
// print_string_center(progress_sy - 21, COLOR_PROGRESS_TEXT, COLOR_DIALOG, text);
drawboxfill((unsigned short*)screen_addr, progress_sx, progress_sy, progress_ex,
progress_ey, COLOR16(15, 15, 15));
ds2_flipScreen(_progress_screen_id, 2);
}
// update progress bar
void update_progress(void)
{
void* screen_addr;
if(_progress_screen_id & UP_MASK)
screen_addr = up_screen_addr;
else
screen_addr = down_screen_addr;
int width = (int)( ((float)++progress_current / (float)progress_total) * ((float)SCREEN_WIDTH / 3.0 * 2.0) );
// draw_dialog(progress_sx - 8, progress_sy -29, progress_ex + 8, progress_ey + 13);
// boxfill(progress_sx - 1, progress_sy - 1, progress_ex + 1, progress_ey + 1, COLOR_BLACK);
// if (progress_message[0] != '\0')
// print_string_center(progress_sy - 21, COLOR_PROGRESS_TEXT, COLOR_DIALOG, progress_message);
drawboxfill(screen_addr, progress_sx, progress_sy, progress_sx+width, progress_ey, COLOR16(30, 19, 7));
ds2_flipScreen(_progress_screen_id, 2);
}
// display progress string
void show_progress(char *text)
{
void* screen_addr;
if(_progress_screen_id & UP_MASK)
screen_addr = up_screen_addr;
else
screen_addr = down_screen_addr;
// draw_dialog(progress_sx - 8, progress_sy -29, progress_ex + 8, progress_ey + 13);
// boxfill(progress_sx - 1, progress_sy - 1, progress_ex + 1, progress_ey + 1, COLOR_BLACK);
if (progress_current)
{
int width = (int)( (float)(++progress_current / progress_total) * (float)(SCREEN_WIDTH / 3.0 * 2.0) );
drawboxfill(screen_addr, progress_sx, progress_sy, progress_sx+width, progress_ey, COLOR16(30, 19, 7));
}
// if (text[0] != '\0')
// print_string_center(progress_sy - 21, COLOR_PROGRESS_TEXT, COLOR_DIALOG, text);
ds2_flipScreen(_progress_screen_id, 2);
// OSTimeDly(progress_wait);
mdelay(500);
}
/* /*
* Drawing scroll bar * Drawing scroll bar
*/ */
@ -1107,62 +1281,6 @@ int icon_init(u32 language_id)
return ret; return ret;
} }
int color_init()
{
char path[MAX_PATH];
char current_line[256];
sprintf(path, "%s/%s/%s", main_path, GUI_SOURCE_PATH, "uicolors.txt");
FILE* fp = fopen(path, "r");
if (fp != NULL)
{
while(fgets(current_line, 256, fp))
{
char* colon = strchr(current_line, ':');
if (colon)
{
*colon = '\0';
u16* color = NULL;
if (strcasecmp(current_line, "Background") == 0)
color = &COLOR_BG;
else if (strcasecmp(current_line, "ActiveItem") == 0)
color = &COLOR_ACTIVE_ITEM;
else if (strcasecmp(current_line, "InactiveItem") == 0)
color = &COLOR_INACTIVE_ITEM;
else if (strcasecmp(current_line, "MessageText") == 0)
color = &COLOR_MSSG;
else if (strcasecmp(current_line, "ActiveMain") == 0)
color = &COLOR_ACTIVE_MAIN;
else if (strcasecmp(current_line, "InactiveMain") == 0)
color = &COLOR_INACTIVE_MAIN;
if (color != NULL)
{
char* end = strchr(colon + 1, '\0') - 1;
while (*end && (*end == '\r' || *end == '\n'))
*end-- = '\0';
char* ptr = colon + 1;
while (*ptr && *ptr == ' ')
ptr++;
u32 color32;
u8 r, g, b;
if (strlen(ptr) == 7 && *ptr == '#')
{
color32 = strtol(ptr + 1, NULL, 16);
r = (color32 >> 16) & 0xFF;
g = (color32 >> 8) & 0xFF;
b = color32 & 0xFF;
*color = COLOR16(r >> 3, g >> 3, b >> 3);
}
}
}
}
fclose(fp);
return 0;
}
else
return 1;
}
/*************************************************************/ /*************************************************************/
void show_icon(void* screen, struct gui_iconlist* icon, u32 x, u32 y) void show_icon(void* screen, struct gui_iconlist* icon, u32 x, u32 y)
{ {
@ -1173,24 +1291,16 @@ void show_icon(void* screen, struct gui_iconlist* icon, u32 x, u32 y)
dst = (unsigned short*)screen + y*NDS_SCREEN_WIDTH + x; dst = (unsigned short*)screen + y*NDS_SCREEN_WIDTH + x;
if(NULL == src) return; //The icon may initialized failure if(NULL == src) return; //The icon may initialized failure
if (icon->x == NDS_SCREEN_WIDTH && icon->y == NDS_SCREEN_HEIGHT && x == 0 && y == 0) for(i= 0; i < icon->y; i++)
{ {
// Don't support transparency for a background. for(k= 0; k < icon->x; k++)
memcpy(dst, src, NDS_SCREEN_WIDTH * NDS_SCREEN_HEIGHT * sizeof(u16));
}
else
{
for(i= 0; i < icon->y; i++)
{ {
for(k= 0; k < icon->x; k++) if(0x03E0 != *src) dst[k]= *src;
{ src++;
if(0x03E0 != *src) dst[k]= *src;
src++;
}
dst += NDS_SCREEN_WIDTH;
} }
}
dst += NDS_SCREEN_WIDTH;
}
} }
/*************************************************************/ /*************************************************************/
@ -1263,7 +1373,7 @@ void show_log(void* screen_addr)
void err_msg(enum SCREEN_ID screen, char *msg) void err_msg(enum SCREEN_ID screen, char *msg)
{ {
// A wild console appeared! // A wild console appeared!
ConsoleInit(RGB15(31, 31, 31), RGB15(0, 0, 0), UP_SCREEN, 2); ConsoleInit(RGB15(31, 31, 31), RGB15(0, 0, 0), UP_SCREEN, 512);
printf(msg); printf(msg);
} }

View file

@ -61,25 +61,27 @@
#define COLOR_TRANS COLOR16(31, 31, 63) #define COLOR_TRANS COLOR16(31, 31, 63)
#define COLOR_WHITE COLOR16(31, 31, 31) #define COLOR_WHITE COLOR16(31, 31, 31)
#define COLOR_BLACK COLOR16( 0, 0, 0) #define COLOR_BLACK COLOR16( 0, 0, 0)
//#define COLOR_TEXT COLOR16(31, 31, 31) #define COLOR_TEXT COLOR16(31, 31, 31)
//#define COLOR_PROGRESS_TEXT COLOR16( 0, 0, 0) #define COLOR_PROGRESS_TEXT COLOR16( 0, 0, 0)
//#define COLOR_PROGRESS_BAR COLOR16(15, 15, 15) #define COLOR_PROGRESS_BAR COLOR16(15, 15, 15)
//#define COLOR_ERROR COLOR16(31, 0, 0) #define COLOR_ERROR COLOR16(31, 0, 0)
//#define COLOR_BG COLOR16(2, 4, 10) #define COLOR_BG COLOR16(2, 4, 10)
//#define COLOR_BG32 COLOR32(2*8, 4*8, 10*8) #define COLOR_BG32 COLOR32(2*8, 4*8, 10*8)
//#define COLOR_ROM_INFO COLOR16(22, 18, 26) #define COLOR_ROM_INFO COLOR16(22, 18, 26)
//#define COLOR_HELP_TEXT COLOR16(16, 20, 24) #define COLOR_ACTIVE_ITEM COLOR16(31, 31, 31)
//#define COLOR_DIALOG COLOR16(31, 31, 31) #define COLOR_INACTIVE_ITEM COLOR16(11, 7, 19)
//#define COLOR_DIALOG_SHADOW COLOR16( 0, 2, 8) #define COLOR_HELP_TEXT COLOR16(16, 20, 24)
//#define COLOR_FRAME COLOR16( 0, 0, 0) #define COLOR_DIALOG COLOR16(31, 31, 31)
//#define COLOR_YESNO_TEXT COLOR16( 0, 0, 0) #define COLOR_DIALOG_SHADOW COLOR16( 0, 2, 8)
//#define COLOR_GREEN COLOR16( 0, 31, 0 ) #define COLOR_FRAME COLOR16( 0, 0, 0)
//#define COLOR_GREEN1 COLOR16( 0, 24, 0 ) #define COLOR_YESNO_TEXT COLOR16( 0, 0, 0)
//#define COLOR_GREEN2 COLOR16( 0, 18, 0 ) #define COLOR_GREEN COLOR16( 0, 31, 0 )
//#define COLOR_GREEN3 COLOR16( 0, 12, 0 ) #define COLOR_GREEN1 COLOR16( 0, 24, 0 )
//#define COLOR_GREEN4 COLOR16( 0, 6, 0 ) #define COLOR_GREEN2 COLOR16( 0, 18, 0 )
//#define COLOR_RED COLOR16( 31, 0, 0 ) #define COLOR_GREEN3 COLOR16( 0, 12, 0 )
//#define COLOR_MSSG COLOR16( 16, 8, 29) #define COLOR_GREEN4 COLOR16( 0, 6, 0 )
#define COLOR_RED COLOR16( 31, 0, 0 )
#define COLOR_MSSG COLOR16( 16, 8, 29)
/****************************************************************************** /******************************************************************************
* *
******************************************************************************/ ******************************************************************************/
@ -87,13 +89,6 @@
extern "C" { extern "C" {
#endif #endif
extern u16 COLOR_BG;
extern u16 COLOR_INACTIVE_ITEM;
extern u16 COLOR_ACTIVE_ITEM;
extern u16 COLOR_MSSG;
extern u16 COLOR_INACTIVE_MAIN;
extern u16 COLOR_ACTIVE_MAIN;
struct background{ struct background{
char bgname[128]; char bgname[128];
char bgbuffer[256*192*2]; char bgbuffer[256*192*2];
@ -166,14 +161,15 @@ extern void draw_message(void* screen_address, u16 *screen_bg, u32 sx, u32 sy, u
extern void draw_string_vcenter(void* screen_address, u32 sx, u32 sy, u32 width, extern void draw_string_vcenter(void* screen_address, u32 sx, u32 sy, u32 width,
u32 color_fg, char *string); u32 color_fg, char *string);
#define MAX_SCROLL_STRING 16 #define MAX_SCROLL_STRING 8
extern u32 hscroll_init(void* screen_address, u32 sx, u32 sy, u32 width,
u32 color_bg, u32 color_fg, char *string);
extern u32 draw_hscroll_init(void* screen_address, u32 sx, u32 sy, u32 width, extern u32 draw_hscroll_init(void* screen_address, u32 sx, u32 sy, u32 width,
u32 color_bg, u32 color_fg, char *string); u32 color_bg, u32 color_fg, char *string);
extern u32 draw_hscroll(u32 index, s32 scroll_val); extern u32 draw_hscroll(u32 index, s32 scroll_val);
extern void draw_hscroll_over(u32 index); extern void draw_hscroll_over(u32 index);
extern void boxfill_alpha(u32 sx, u32 sy, u32 ex, u32 ey, u32 color, u32 alpha); extern void boxfill_alpha(u32 sx, u32 sy, u32 ex, u32 ey, u32 color, u32 alpha);
extern void init_progress(enum SCREEN_ID screen, u32 total, char *text);
extern void update_progress(void);
extern void show_progress(char *text);
extern void scrollbar(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey, u32 all, u32 view, u32 now); extern void scrollbar(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey, u32 all, u32 view, u32 now);
extern u32 yesno_dialog(char *text); extern u32 yesno_dialog(char *text);
extern u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no); extern u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no);
@ -185,7 +181,6 @@ extern void msg_screen_clear(void);
extern void msg_set_text_color(u32 color); extern void msg_set_text_color(u32 color);
extern int icon_init(u32 language_id); extern int icon_init(u32 language_id);
extern int color_init(void);
extern int gui_change_icon(u32 language_id); extern int gui_change_icon(u32 language_id);
extern int show_background(void *screen, char *bgname); extern int show_background(void *screen, char *bgname);
extern void show_icon(void* screen, struct gui_iconlist *icon, u32 x, u32 y); extern void show_icon(void* screen, struct gui_iconlist *icon, u32 x, u32 y);

View file

@ -33,12 +33,6 @@ void S9xProcessSound (unsigned int);
char *rom_filename = NULL; char *rom_filename = NULL;
char *SDD1_pack = NULL; char *SDD1_pack = NULL;
/*
* It is only safe to manipulate saved states between frames.
*/
static bool8 LoadStateNeeded = FALSE;
static bool8 SaveStateNeeded = FALSE;
static u8 Buf[MAX_BUFFER_SIZE]; static u8 Buf[MAX_BUFFER_SIZE];
#define FIXED_POINT 0x10000 #define FIXED_POINT 0x10000
@ -140,29 +134,22 @@ bool8 S9xInitUpdate ()
} }
extern void NDSSFCDrawFrameAntialiased(void* screen_addr); extern void NDSSFCDrawFrameAntialiased();
bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/) bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
{ {
void* screen_addr = emu_config.BottomScreenGame
? down_screen_addr
: up_screen_addr;
SCREEN_ID screen_num = emu_config.BottomScreenGame
? DOWN_SCREEN
: UP_SCREEN;
switch(game_config.graphic) switch(game_config.graphic)
{ {
//Up //Up
case 1: case 1:
#ifdef DS2_DMA #ifdef DS2_DMA
__dcache_writeback_all(); __dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2); ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2);
ds2_DMA_wait(1); ds2_DMA_wait(1);
ds2_DMA_stop(1); ds2_DMA_stop(1);
#else #else
memcpy(screen_addr, GFX.Screen+256*32*2, 256*192*2); memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2);
#endif #endif
break; break;
@ -170,11 +157,11 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
case 2: case 2:
#ifdef DS2_DMA #ifdef DS2_DMA
__dcache_writeback_all(); __dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen, 256 * 192 * 2); ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2);
ds2_DMA_wait(1); ds2_DMA_wait(1);
ds2_DMA_stop(1); ds2_DMA_stop(1);
#else #else
memcpy(screen_addr, GFX.Screen, 256*192*2); memcpy(up_screen_addr, GFX.Screen, 256*192*2);
#endif #endif
break; break;
@ -182,16 +169,16 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
case 3: case 3:
#ifdef DS2_DMA #ifdef DS2_DMA
__dcache_writeback_all(); __dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2); ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2);
ds2_DMA_wait(1); ds2_DMA_wait(1);
ds2_DMA_stop(1); ds2_DMA_stop(1);
#else #else
memcpy(screen_addr, GFX.Screen+256*16*2, 256*192*2); memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2);
#endif #endif
break; break;
case 4: case 4:
NDSSFCDrawFrameAntialiased (screen_addr); NDSSFCDrawFrameAntialiased ();
break; break;
@ -204,7 +191,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
register unsigned int m; register unsigned int m;
src = GFX.Screen; src = GFX.Screen;
dst = (unsigned char*)screen_addr; dst = (unsigned char*)up_screen_addr;
for(m = 0; m < 32; m++) for(m = 0; m < 32; m++)
{ {
#ifdef DS2_DMA #ifdef DS2_DMA
@ -221,7 +208,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
break; break;
} }
ds2_flipScreen(screen_num, UP_SCREEN_UPDATE_METHOD); ds2_flipScreen(UP_SCREEN, UP_SCREEN_UPDATE_METHOD);
// A problem with update method 1 (wait, double buffer) means that, after // A problem with update method 1 (wait, double buffer) means that, after
// about 15 minutes of play time, the screen starts to half-redraw every // about 15 minutes of play time, the screen starts to half-redraw every
// frame. With update method 0, this is mitigated. (Method 2 is too slow.) // frame. With update method 0, this is mitigated. (Method 2 is too slow.)
@ -419,20 +406,6 @@ void game_set_fluidity()
} }
} }
void game_set_retro(void)
{
if (game_config.RetroSound == 1)
{
Settings.InterpolatedSound = FALSE;
S9xSetEightBitConsoleSound (TRUE);
}
else
{
Settings.InterpolatedSound = TRUE;
S9xSetEightBitConsoleSound (FALSE);
}
}
void init_sfc_setting(void) void init_sfc_setting(void)
{ {
ZeroMemory (&Settings, sizeof (Settings)); ZeroMemory (&Settings, sizeof (Settings));
@ -451,7 +424,8 @@ void init_sfc_setting(void)
Settings.DisableSoundEcho = FALSE; Settings.DisableSoundEcho = FALSE;
//sound settings //sound settings
Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; Settings.APUEnabled = Settings.NextAPUEnabled = TRUE;
// Settings.FixFrequency = 1; Settings.FixFrequency = 1;
Settings.InterpolatedSound = TRUE;
Settings.H_Max = SNES_CYCLES_PER_SCANLINE; Settings.H_Max = SNES_CYCLES_PER_SCANLINE;
Settings.SkipFrames = AUTO_FRAMERATE; Settings.SkipFrames = AUTO_FRAMERATE;
@ -639,40 +613,16 @@ int sfc_main (int argc, char **argv)
} }
else else
#endif #endif
if (Settings.Paused)
{ {
if (SaveStateNeeded) { S9xSetSoundMute (TRUE);
QuickSaveState (); unsigned short screen[256*192];
SaveStateNeeded = FALSE;
}
if (LoadStateNeeded) { copy_screen((void*)screen, up_screen_addr, 0, 0, 256, 192);
QuickLoadState (); menu(screen, FirstInvocation);
LoadStateNeeded = FALSE; FirstInvocation = FALSE;
} game_disableAudio();
Settings.Paused = 0;
if (Settings.Paused)
{
S9xSetSoundMute (TRUE);
unsigned short screen[256*192];
if (FirstInvocation) {
memset(screen, 0, sizeof(screen));
}
else {
S9xDeinitUpdate(256, 224, TRUE);
void* screen_addr = emu_config.BottomScreenGame
? down_screen_addr
: up_screen_addr;
copy_screen((void*)screen, screen_addr, 0, 0, 256, 192);
}
menu(screen, FirstInvocation);
FirstInvocation = FALSE;
game_disableAudio();
Settings.Paused = 0;
}
} }
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
@ -695,6 +645,7 @@ void S9xSyncSpeed ()
{ {
uint32 syncnow; uint32 syncnow;
int32 syncdif; int32 syncdif;
unsigned int LastAutoCPUFrequency = AutoCPUFrequency;
#if 0 #if 0
if (Settings.SoundSync == 2) if (Settings.SoundSync == 2)
@ -1233,9 +1184,6 @@ const unsigned int keymap[12] = {
*/ */
static bool8 SoundToggleWasHeld = FALSE; static bool8 SoundToggleWasHeld = FALSE;
static bool8 LoadStateWasHeld = FALSE;
static bool8 SaveStateWasHeld = FALSE;
static bool8 ToggleFullScreenWasHeld = FALSE;
#ifdef ACCUMULATE_JOYPAD #ifdef ACCUMULATE_JOYPAD
// These are kept as DS key bitfields until it's time to send them to Snes9x. // These are kept as DS key bitfields until it's time to send them to Snes9x.
@ -1281,22 +1229,16 @@ uint32 S9xReadJoypad (int which1)
mdelay(1); mdelay(1);
} while (inputdata.key & KEY_LID); } while (inputdata.key & KEY_LID);
ds2_wakeup(); ds2_wakeup();
// Before starting to emulate again, turn on only the // Before starting to emulate again, turn off the lower
// game screen's backlight. // screen's backlight.
SCREEN_ID screen_num = emu_config.BottomScreenGame
? DOWN_SCREEN
: UP_SCREEN;
mdelay(100); // needed to avoid ds2_setBacklight crashing mdelay(100); // needed to avoid ds2_setBacklight crashing
ds2_setBacklight(3 - screen_num); ds2_setBacklight(2);
GameFrequencyCPU(); GameFrequencyCPU();
} }
u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu; u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu;
u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward; u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward;
u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound; u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound;
u32 HotkeyQuickLoadState = game_config.HotkeyQuickLoadState != 0 ? game_config.HotkeyQuickLoadState : emu_config.HotkeyQuickLoadState;
u32 HotkeyQuickSaveState = game_config.HotkeyQuickSaveState != 0 ? game_config.HotkeyQuickSaveState : emu_config.HotkeyQuickSaveState;
u32 HotkeyToggleFullScreen = game_config.HotkeyToggleFullScreen != 0 ? game_config.HotkeyToggleFullScreen : emu_config.HotkeyToggleFullScreen;
if(Controls & KEY_TOUCH || if(Controls & KEY_TOUCH ||
(HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu)) (HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu))
@ -1319,37 +1261,6 @@ uint32 S9xReadJoypad (int which1)
SoundToggleWasHeld = SoundToggleIsHeld; SoundToggleWasHeld = SoundToggleIsHeld;
/* It is only safe to load/save a state between frames.
* entry.cpp:sfc_main will pick this up. */
bool8 LoadStateIsHeld =
(HotkeyQuickLoadState && ((Controls & HotkeyQuickLoadState) == HotkeyQuickLoadState))
;
if (LoadStateIsHeld && !LoadStateWasHeld)
LoadStateNeeded = TRUE;
LoadStateWasHeld = LoadStateIsHeld;
bool8 SaveStateIsHeld =
(HotkeyQuickSaveState && ((Controls & HotkeyQuickSaveState) == HotkeyQuickSaveState))
;
if (SaveStateIsHeld && !SaveStateWasHeld)
SaveStateNeeded = TRUE;
SaveStateWasHeld = SaveStateIsHeld;
/* Full-screen toggle? */
bool8 ToggleFullScreenIsHeld =
(HotkeyToggleFullScreen && ((Controls & HotkeyToggleFullScreen) == HotkeyToggleFullScreen))
;
if (ToggleFullScreenIsHeld && !ToggleFullScreenWasHeld) {
ToggleFullScreen ();
}
ToggleFullScreenWasHeld = ToggleFullScreenIsHeld;
uint32 key = 0x80000000; // Required by Snes9x uint32 key = 0x80000000; // Required by Snes9x
// DS -> SNES // DS -> SNES

View file

@ -1,11 +1,6 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void game_disableAudio();
void game_set_frameskip();
void game_set_fluidity();
void game_set_retro();
int game_load_state(char* file); int game_load_state(char* file);
int game_save_state(char* file); int game_save_state(char* file);
void S9xAutoSaveSRAM (); void S9xAutoSaveSRAM ();
@ -13,6 +8,8 @@ extern "C" {
void game_restart(void); void game_restart(void);
int load_gamepak(const char* file); int load_gamepak(const char* file);
extern unsigned int AutoCPUFrequency;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -26,7 +26,7 @@ extern "C" {
#include "cheats.h" #include "cheats.h"
#define CHEATS_PER_PAGE 6 #define CHEATS_PER_PAGE 4
#define MAX_CHEATS_PAGE (MAX_CHEATS_T / CHEATS_PER_PAGE) #define MAX_CHEATS_PAGE (MAX_CHEATS_T / CHEATS_PER_PAGE)
extern int NDSSFCLoadCheatFile(const char* filename); extern int NDSSFCLoadCheatFile(const char* filename);

File diff suppressed because it is too large Load diff

View file

@ -27,46 +27,6 @@
#define UP_SCREEN_UPDATE_METHOD 0 #define UP_SCREEN_UPDATE_METHOD 0
#define DOWN_SCREEN_UPDATE_METHOD 2 #define DOWN_SCREEN_UPDATE_METHOD 2
// For general option text
#define OPTION_TEXT_X 10
#define OPTION_TEXT_SX 236
// For option rows
#define GUI_ROW1_Y 36
#define GUI_ROW_SY 19
// The following offset is added to the row's Y coordinate to provide
// the Y coordinate for its text.
#define TEXT_OFFSET_Y 2
// The following offset is added to the row's Y coordinate to provide
// the Y coordinate for its ICON_SUBSELA (sub-screen selection type A).
#define SUBSELA_OFFSET_Y -2
#define SUBSELA_X ((NDS_SCREEN_WIDTH - ICON_SUBSELA.x) / 2)
// For message boxes
#define MESSAGE_BOX_TEXT_X ((NDS_SCREEN_WIDTH - ICON_MSG.x) / 2 + 3)
#define MESSAGE_BOX_TEXT_SX (ICON_MSG.x - 6)
// Y is brought down by the "window title" that's part of ICON_MSG
#define MESSAGE_BOX_TEXT_Y ((NDS_SCREEN_HEIGHT - ICON_MSG.y) / 2 + 24)
// For cheats [ NUM. DESC . . . . . +/- ]
#define CHEAT_NUMBER_X 10
#define CHEAT_DESC_X 34
#define CHEAT_DESC_SX 197
#define CHEAT_ACTIVE_X 241
// For the file selector
#define FILE_SELECTOR_ICON_X 10
#define FILE_SELECTOR_ICON_Y (TEXT_OFFSET_Y - 1)
#define FILE_SELECTOR_NAME_X 32
#define FILE_SELECTOR_NAME_SX 214
// Back button
#define BACK_BUTTON_X 229
#define BACK_BUTTON_Y 10
// Title icon
#define TITLE_ICON_X 12
#define TITLE_ICON_Y 9
#define MAX_GAMEPAD_MAP 16 #define MAX_GAMEPAD_MAP 16
#ifdef __cplusplus #ifdef __cplusplus
@ -83,11 +43,7 @@ struct _EMU_CONFIG
u32 HotkeyReturnToMenu; u32 HotkeyReturnToMenu;
u32 HotkeyTemporaryFastForward; u32 HotkeyTemporaryFastForward;
u32 HotkeyToggleSound; u32 HotkeyToggleSound;
u32 HotkeyQuickLoadState; u32 Reserved[61];
u32 HotkeyQuickSaveState;
u32 HotkeyToggleFullScreen;
u32 BottomScreenGame;
u32 Reserved[57];
}; };
struct _GAME_CONFIG struct _GAME_CONFIG
@ -116,11 +72,7 @@ struct _GAME_CONFIG
* THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0. * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0.
*/ */
u32 PreviouslyUsed_20130206_2; u32 PreviouslyUsed_20130206_2;
u32 RetroSound; u32 Reserved2[42];
u32 HotkeyQuickLoadState;
u32 HotkeyQuickSaveState;
u32 HotkeyToggleFullScreen;
u32 Reserved2[38];
}; };
typedef enum typedef enum
@ -164,6 +116,7 @@ extern char main_path[MAX_PATH];
extern char rom_path[MAX_PATH]; extern char rom_path[MAX_PATH];
extern u32 game_enable_audio; extern u32 game_enable_audio;
extern u32 clock_speed_number;
extern u32 game_fast_forward; extern u32 game_fast_forward;
extern u32 temporary_fast_forward; extern u32 temporary_fast_forward;
@ -185,14 +138,12 @@ extern GAME_CONFIG game_config;
******************************************************************************/ ******************************************************************************/
extern void gui_init(u32 lang_id); extern void gui_init(u32 lang_id);
extern u32 menu(u16 *original_screen, bool8 FirstInvocation); extern u32 menu(u16 *original_screen, bool8 FirstInvocation);
extern void game_disableAudio();
extern void game_set_frameskip();
extern void game_set_fluidity();
extern void LowFrequencyCPU(); extern void LowFrequencyCPU();
extern void HighFrequencyCPU(); extern void HighFrequencyCPU();
extern void GameFrequencyCPU(); extern void GameFrequencyCPU();
extern void QuickSaveState();
extern void QuickLoadState();
extern void ToggleFullScreen();
extern int load_language_msg(char *filename, u32 language); extern int load_language_msg(char *filename, u32 language);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -31,19 +31,13 @@ enum MSG
MSG_MAIN_MENU_TOOLS, MSG_MAIN_MENU_TOOLS,
MSG_MAIN_MENU_OPTIONS, MSG_MAIN_MENU_OPTIONS,
MSG_MAIN_MENU_EXIT, MSG_MAIN_MENU_EXIT,
MSG_FILE_MENU_LOADING_LIST,
MSG_FILE_MENU_SORTING_LIST,
FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE, FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE,
MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO, MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO,
MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO, MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO,
FMT_VIDEO_ASPECT_RATIO, FMT_VIDEO_ASPECT_RATIO,
FMT_VIDEO_FAST_FORWARD, FMT_VIDEO_FAST_FORWARD,
FMT_VIDEO_FRAME_SKIPPING, FMT_VIDEO_FRAME_SKIPPING,
FMT_VIDEO_GAME_SCREEN,
FMT_AUDIO_SOUND, FMT_AUDIO_SOUND,
FMT_AUDIO_RETRO_SOUND,
FMT_SAVED_STATE_CREATE, FMT_SAVED_STATE_CREATE,
FMT_SAVED_STATE_LOAD, FMT_SAVED_STATE_LOAD,
MSG_SAVED_STATE_DELETE_GENERAL, MSG_SAVED_STATE_DELETE_GENERAL,
@ -68,9 +62,6 @@ enum MSG
MSG_HOTKEY_MAIN_MENU, MSG_HOTKEY_MAIN_MENU,
MSG_HOTKEY_TEMPORARY_FAST_FORWARD, MSG_HOTKEY_TEMPORARY_FAST_FORWARD,
MSG_HOTKEY_SOUND_TOGGLE, MSG_HOTKEY_SOUND_TOGGLE,
MSG_HOTKEY_QUICK_LOAD_STATE,
MSG_HOTKEY_QUICK_SAVE_STATE,
MSG_HOTKEY_FULL_SCREEN_TOGGLE,
MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS,
MSG_HOTKEY_DELETE_WITH_A, MSG_HOTKEY_DELETE_WITH_A,
MSG_HOTKEY_CANCEL_WITH_B, MSG_HOTKEY_CANCEL_WITH_B,
@ -97,9 +88,6 @@ enum MSG
MSG_VIDEO_FRAME_SKIPPING_9, MSG_VIDEO_FRAME_SKIPPING_9,
MSG_VIDEO_FRAME_SKIPPING_10, MSG_VIDEO_FRAME_SKIPPING_10,
MSG_VIDEO_GAME_SCREEN_TOP,
MSG_VIDEO_GAME_SCREEN_BOTTOM,
MSG_GENERAL_OFF, MSG_GENERAL_OFF,
MSG_GENERAL_ON, MSG_GENERAL_ON,
@ -136,7 +124,12 @@ enum MSG
MSG_NO_SLIDE, MSG_NO_SLIDE,
MSG_PLAYING_SLIDE, MSG_PLAYING_SLIDE,
MSG_PAUSE_SLIDE, MSG_PAUSE_SLIDE,
MSG_SCREENSHOT_SLIDESHOW_KEYS, MSG_PLAY_SLIDE1,
MSG_PLAY_SLIDE2,
MSG_PLAY_SLIDE3,
MSG_PLAY_SLIDE4,
MSG_PLAY_SLIDE5,
MSG_PLAY_SLIDE6,
MSG_PROGRESS_LOADING_GAME, MSG_PROGRESS_LOADING_GAME,
@ -155,12 +148,10 @@ enum LANGUAGE {
FRENCH, FRENCH,
GERMAN, GERMAN,
DUTCH, DUTCH,
SPANISH, SPANISH
ITALIAN,
PORTUGUESE_BRAZILIAN
}; };
extern char* lang[8]; // Allocated in gui.c, needs to match the languages ^ extern char* lang[6]; // Allocated in gui.c, needs to match the languages ^
char *msg[MSG_END+1]; char *msg[MSG_END+1];
char msg_data[32 * 1024]; char msg_data[32 * 1024];

View file

@ -337,7 +337,6 @@ struct SSettings{
#ifndef FOREVER_16_BIT_SOUND #ifndef FOREVER_16_BIT_SOUND
bool8 SixteenBitSound; bool8 SixteenBitSound;
#endif #endif
bool8 EightBitConsoleSound; // due to caching, this needs S9xSetEightBitConsoleSound()
int SoundBufferSize; int SoundBufferSize;
int SoundMixInterval; int SoundMixInterval;
bool8 SoundEnvelopeHeightReading; bool8 SoundEnvelopeHeightReading;

View file

@ -168,19 +168,6 @@ extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *);
#define LAST_SAMPLE 0xffffff #define LAST_SAMPLE 0xffffff
#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE)
void S9xSetEightBitConsoleSound (bool8 Enabled)
{
if (Settings.EightBitConsoleSound != Enabled)
{
Settings.EightBitConsoleSound = Enabled;
int i;
for (i = 0; i < 8; i++)
{
SoundData.channels[i].needs_decode = TRUE;
}
}
}
STATIC inline uint8 *S9xGetSampleAddress (int sample_number) STATIC inline uint8 *S9xGetSampleAddress (int sample_number)
{ {
uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff); uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff);
@ -832,263 +819,74 @@ void DecodeBlock (Channel *ch)
ch->block = ch->decoded; ch->block = ch->decoded;
return; return;
} }
signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
if (Settings.EightBitConsoleSound) filter = *compressed;
if ((ch->last_block = filter & 1))
ch->loop = (filter & 2) != 0;
compressed++;
signed short *raw = ch->block = ch->decoded;
// Seperate out the header parts used for decoding
shift = filter >> 4;
// Header validity check: if range(shift) is over 12, ignore
// all bits of the data for that block except for the sign bit of each
invalid_header = (shift >= 0xD);
filter = filter&0x0c;
int32 prev0 = ch->previous [0];
int32 prev1 = ch->previous [1];
for (i = 8; i != 0; i--)
{ {
signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; sample1 = *compressed++;
sample2 = sample1 << 4;
//Sample 2 = Bottom Nibble, Sign Extended.
sample2 >>= 4;
//Sample 1 = Top Nibble, shifted down and Sign Extended.
sample1 >>= 4;
if (invalid_header) { sample1>>=3; sample2>>=3; }
filter = *compressed; for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){
if ((ch->last_block = filter & 1)) out=(((nybblesmp) ? sample2 : sample1) << shift);
ch->loop = (filter & 2) != 0; out >>= 1;
int16 interim[16]; switch(filter)
uint8 interim_byte = 0;
compressed++;
signed short *raw = ch->block = ch->decoded;
// Seperate out the header parts used for decoding
shift = filter >> 4;
// Header validity check: if range(shift) is over 12, ignore
// all bits of the data for that block except for the sign bit of each
invalid_header = (shift >= 0xD);
filter = filter&0x0c;
int32 prev0 = ch->previous [0];
int32 prev1 = ch->previous [1];
int16 amplitude = 0;
for (i = 8; i != 0; i--)
{
sample1 = *compressed++;
sample2 = sample1 << 4;
//Sample 2 = Bottom Nibble, Sign Extended.
sample2 >>= 4;
//Sample 1 = Top Nibble, shifted down and Sign Extended.
sample1 >>= 4;
if (invalid_header) { sample1>>=3; sample2>>=3; }
for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){
out=(((nybblesmp) ? sample2 : sample1) << shift);
out >>= 1;
switch(filter)
{
case 0x00:
// Method0 - [Smp]
break;
case 0x04:
// Method1 - [Delta]+[Smp-1](15/16)
out+=(prev0>>1)+((-prev0)>>5);
break;
case 0x08:
// Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16)
out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5);
break;
default:
// Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16)
out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4);
break;
}
CLIP16(out);
int16 result = (signed short)(out<<1);
if (abs(result) > amplitude)
amplitude = abs(result);
interim[interim_byte++] = out;
prev1=(signed short)prev0;
prev0=(signed short)(out<<1);
}
}
ch->previous [0] = prev0;
ch->previous [1] = prev1;
int32 total_deviation_from_previous = 0;
for (i = 1; i < 16; i++)
total_deviation_from_previous += abs(interim[i] - interim[i - 1]);
if (total_deviation_from_previous >= (int32) amplitude * 4)
{
/* Looks like noise. Generate noise. */
for (i = 0; i < 16; i++)
{ {
int feedback = (noise_gen << 13) ^ (noise_gen << 14); case 0x00:
noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); // Method0 - [Smp]
ch->decoded[i] = (noise_gen << 17) >> 17; break;
case 0x04:
// Method1 - [Delta]+[Smp-1](15/16)
out+=(prev0>>1)+((-prev0)>>5);
break;
case 0x08:
// Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16)
out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5);
break;
default:
// Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16)
out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4);
break;
} }
} CLIP16(out);
else if (interim[0] < interim[1] && interim[1] < interim[2] *raw++ = (signed short)(out<<1);
&& interim[2] < interim[3] prev1=(signed short)prev0;
&& interim[4] > interim[5] && interim[5] > interim[6] prev0=(signed short)(out<<1);
&& interim[6] > interim[7] && interim[7] > interim[8]
&& interim[8] > interim[9] && interim[9] > interim[10]
&& interim[10] > interim[11]
&& interim[12] < interim[13] && interim[13] < interim[14]
&& interim[14] < interim[15])
{
/* Looks like a sine or triangle wave. Make it a
* triangle wave with an amplitude equivalent to that
* of the highest amplitude sample of the block. */
ch->decoded[0] = ch->decoded[8] = 0;
ch->decoded[1] = ch->decoded[7] = amplitude / 4;
ch->decoded[2] = ch->decoded[6] = amplitude / 2;
ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4;
ch->decoded[4] = amplitude;
ch->decoded[9] = ch->decoded[15] = -(amplitude / 4);
ch->decoded[10] = ch->decoded[14] = -(amplitude / 2);
ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4);
ch->decoded[12] = -amplitude;
}
else if (interim[0] > interim[1] && interim[1] > interim[2]
&& interim[2] > interim[3]
&& interim[4] < interim[5] && interim[5] < interim[6]
&& interim[6] < interim[7] && interim[7] < interim[8]
&& interim[8] < interim[9] && interim[9] < interim[10]
&& interim[10] < interim[11]
&& interim[12] > interim[13] && interim[13] > interim[14]
&& interim[14] > interim[15])
{
/* Inverted triangle wave. */
ch->decoded[0] = ch->decoded[8] = 0;
ch->decoded[1] = ch->decoded[7] = -(amplitude / 4);
ch->decoded[2] = ch->decoded[6] = -(amplitude / 2);
ch->decoded[3] = ch->decoded[5] = -(amplitude * 3 / 4);
ch->decoded[4] = -amplitude;
ch->decoded[9] = ch->decoded[15] = amplitude / 4;
ch->decoded[10] = ch->decoded[14] = amplitude / 2;
ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4;
ch->decoded[12] = amplitude;
}
else if (interim[0] < interim[1] && interim[1] < interim[2]
&& interim[2] < interim[3] && interim[3] < interim[4]
&& interim[4] < interim[5] && interim[5] < interim[6]
&& interim[6] < interim[7]
&& interim[8] > interim[9] && interim[9] > interim[10]
&& interim[10] > interim[11] && interim[11] > interim[12]
&& interim[12] > interim[13] && interim[13] > interim[14]
&& interim[14] > interim[15])
{
/* Looks like a V wave. Make it a half-triangle wave
* with an amplitude equivalent to that
* of the highest amplitude sample of the block. */
ch->decoded[0] = 0;
ch->decoded[1] = ch->decoded[15] = amplitude / 8;
ch->decoded[2] = ch->decoded[14] = amplitude / 4;
ch->decoded[3] = ch->decoded[13] = amplitude * 3 / 8;
ch->decoded[4] = ch->decoded[12] = amplitude / 2;
ch->decoded[5] = ch->decoded[11] = amplitude * 5 / 8;
ch->decoded[6] = ch->decoded[10] = amplitude * 3 / 4;
ch->decoded[7] = ch->decoded[9] = amplitude * 7 / 8;
ch->decoded[8] = amplitude;
}
else if (interim[0] > interim[1] && interim[1] > interim[2]
&& interim[2] > interim[3] && interim[3] > interim[4]
&& interim[4] > interim[5] && interim[5] > interim[6]
&& interim[6] > interim[7]
&& interim[8] < interim[9] && interim[9] < interim[10]
&& interim[10] < interim[11] && interim[11] < interim[12]
&& interim[12] < interim[13] && interim[13] < interim[14]
&& interim[14] < interim[15])
{
/* Inverted V wave. */
ch->decoded[0] = 0;
ch->decoded[1] = ch->decoded[15] = -(amplitude / 8);
ch->decoded[2] = ch->decoded[14] = -(amplitude / 4);
ch->decoded[3] = ch->decoded[13] = -(amplitude * 3 / 8);
ch->decoded[4] = ch->decoded[12] = -(amplitude / 2);
ch->decoded[5] = ch->decoded[11] = -(amplitude * 5 / 8);
ch->decoded[6] = ch->decoded[10] = -(amplitude * 3 / 4);
ch->decoded[7] = ch->decoded[9] = -(amplitude * 7 / 8);
ch->decoded[8] = -amplitude;
}
else
{
// Make it a square wave with an amplitude equivalent to that
// of the highest amplitude sample of the block.
// But actually put half of the amplitude, because
// square waves are just loud.
for (i = 0; i < 8; i++)
ch->decoded[i] = amplitude / 2;
for (i = 8; i < 16; i++)
ch->decoded[i] = -(amplitude / 2);
} }
} }
else ch->previous [0] = prev0;
{ ch->previous [1] = prev1;
signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
filter = *compressed; ch->block_pointer += 9;
if ((ch->last_block = filter & 1))
ch->loop = (filter & 2) != 0;
compressed++;
signed short *raw = ch->block = ch->decoded;
// Seperate out the header parts used for decoding
shift = filter >> 4;
// Header validity check: if range(shift) is over 12, ignore
// all bits of the data for that block except for the sign bit of each
invalid_header = (shift >= 0xD);
filter = filter&0x0c;
int32 prev0 = ch->previous [0];
int32 prev1 = ch->previous [1];
for (i = 8; i != 0; i--)
{
sample1 = *compressed++;
sample2 = sample1 << 4;
//Sample 2 = Bottom Nibble, Sign Extended.
sample2 >>= 4;
//Sample 1 = Top Nibble, shifted down and Sign Extended.
sample1 >>= 4;
if (invalid_header) { sample1>>=3; sample2>>=3; }
for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){
out=(((nybblesmp) ? sample2 : sample1) << shift);
out >>= 1;
switch(filter)
{
case 0x00:
// Method0 - [Smp]
break;
case 0x04:
// Method1 - [Delta]+[Smp-1](15/16)
out+=(prev0>>1)+((-prev0)>>5);
break;
case 0x08:
// Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16)
out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5);
break;
default:
// Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16)
out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4);
break;
}
CLIP16(out);
*raw++ = (signed short)(out<<1);
prev1=(signed short)prev0;
prev0=(signed short)(out<<1);
}
}
ch->previous [0] = prev0;
ch->previous [1] = prev1;
}
ch->block_pointer += 9;
} }
static inline void MixStereo (int sample_count) static inline void MixStereo (int sample_count)

View file

@ -213,15 +213,13 @@ typedef struct
uint32 dummy [3]; uint32 dummy [3];
Channel channels [NUM_CHANNELS]; Channel channels [NUM_CHANNELS];
// bool8 no_filter; // bool8 no_filter;
short master_volume [2]; /* range is -128 .. 127 */ int master_volume [2]; /* range is -128 .. 127 */
short echo_volume [2]; /* range is -128 .. 127 */ int echo_volume [2]; /* range is -128 .. 127 */
int noise_hertz; int noise_hertz;
} SSoundData; } SSoundData;
EXTERN_C SSoundData SoundData; EXTERN_C SSoundData SoundData;
void S9xSetEightBitConsoleSound (bool8 Enabled);
void S9xSetSoundVolume (int channel, short volume_left, short volume_right); void S9xSetSoundVolume (int channel, short volume_left, short volume_right);
void S9xSetSoundFrequency (int channel, int hertz); void S9xSetSoundFrequency (int channel, int hertz);
void S9xSetSoundHertz (int channel, int hertz); void S9xSetSoundHertz (int channel, int hertz);