Compare commits

...

96 commits
1.29 ... master

Author SHA1 Message Date
Nebuleon Fumika
f3dab3957c Release 1.36. 2013-06-16 02:28:00 -04:00
Nebuleon Fumika
010c211443 Remove the reference to splitting the cheat database into two folders. 2013-06-16 02:22:27 -04:00
Nebuleon Fumika
72db4b9ec1 Don't crash on extensionless files. Helps GitHub issue #37 some more. Taken from DS2Compress. 2013-06-16 02:04:08 -04:00
Nebuleon Fumika
a1d1e01e11 Dynamically allocate memory for the file selector to store the name pointers into. Also dramatically simplify the file selector's name management code. This has many effects:
* It allows the file selector to handle directories of more than 511 files and a parent directory entry. (Fixes GitHub issue #37).
* It allows the file selector to sort directories along with files, which is a more common use case (game folders that contain ROM hacks, plus single game files, are sorted by name as the user expects).
* The file selector now reports progress while loading a large directory.
* The screenshot slideshow function now shows an existing dedicated message, "No screenshots found", instead of crashing when the screenshot directory contains no screenshots.

Add Quicksort code from GameYob. See <https://github.com/Nebuleon/GameYob/commit/afbeeba>.

* Faster sorting in the common case where a directory's natural order is already sorted, using the isSorted function.
* Use the median-of-three algorithm first described by Robert Sedgewick to select the pivot. Causes less recursion in many cases.
* Associates file names with their is-directory flag, keeping both in sync.
2013-06-15 23:40:29 -04:00
Nebuleon Fumika
4252250fe7 Prevent a file handle leak when previewing saved states in the row of Load cells. 2013-06-10 22:23:34 -04:00
Nebuleon Fumika
5e5d5dcaa1 L+R takes a screenshot of the Touch Screen in the menu. Taken from TempGBA commit b4a68a9ad710cd37fec0c0f604218f5a34d10fc7. 2013-05-25 12:58:14 -04:00
Nebuleon Fumika
1329a31267 Release 1.35. 2013-05-23 20:09:21 -04:00
Nebuleon Fumika
3f501f9c90 Add support for custom main menu active/inactive, message text and background colors. Fill in default values for the purple skin in uicolors.txt. 2013-05-23 20:07:48 -04:00
kukuasir
5edf465c07 Complete the Simplified Chinese block and rewrite some unclear messages for Chinese speakers. Taken from TempGBA commit 657856afdc0639c446665aa71eeb3003c0bb81ad. 2013-05-21 22:11:16 -04:00
Nebuleon Fumika
3e412a93c5 Complete the Dutch, German, Portuguese (Brazil) and Spanish localisations, aligning some messages to columns for option screens. Taken from TempGBA commit 0b4252dc2f1d6a5c7445ffd6f265e59df277ceef.
* Dutch: Add missing messages. Fix a typo in global button mappings. Thanks to Aeter for this part.
* German: Add missing messages. Thanks to SignZ for this part.
* Portuguese: Add missing messages. Thanks to Diego Liberal for this part.
* Spanish: Add missing messages. Thanks to Boriar for this part.
2013-05-20 18:46:27 -04:00
Nebuleon Fumika
48eb438a24 Fix a bug whereby quick saved states would have a screenshot of "Saving state...". 2013-05-20 17:22:38 -04:00
Nebuleon Fumika
4b5a5a15d7 Add an option to put the game on the Lower Screen.
* Before entering the menu, copy the game screen to the Upper Screen if it's on the Lower Screen.
* Now, the frame that's shown in the menu doesn't appear to be the previous frame for a fraction of a second anymore.
2013-05-20 03:17:02 -04:00
Nebuleon Fumika
41c50b372e CATSFC/system/gui/uicolors.txt: Theme support for active and inactive item text colors. 2013-05-20 00:46:43 -04:00
Nebuleon Fumika
22aa56d2ed Put the most recently played file at the top. This does not introduce an incompatibility with older preference files. 2013-05-20 00:34:33 -04:00
Nebuleon Fumika
fbe8c3fc96 sdk-modifications: Fix totally broken short-file-name (SFN) alias support which caused computers to report duplicate SFNs in directories, as well as corrupted file names and breakage with files that have no extension. 2013-05-17 23:12:43 -04:00
Nebuleon Fumika
6b370ce35b Fix a GUI bug whereby an incorrect item is considered touched in file selectors. 2013-04-28 10:03:00 -04:00
rickvdwetering
0e68b604c6 Update language.msg
Fixed minor Dutch translation errors.
2013-04-16 16:37:27 +03:00
Nebuleon Fumika
53d2f1f6cd Add the year to the date displayed in a saved state's screenshot.
Based on TempGBA commit 0adaf3c332453679cc0a2feee9e87d5a4dc3c771.
2013-04-09 23:14:04 -04:00
Hyura
700a1535d6 Brazilian Portuguese block: Correct typing errors and add missing accents. Imported from TempGBA commit d55e30a2cc4943e74a2d2505c9823dc222e220a3. 2013-04-03 18:15:40 -04:00
Nebuleon Fumika
dfd3934953 Release 1.34. 2013-03-30 03:05:41 -04:00
Nebuleon Fumika
e1eaf42367 Wait for a button to be pressed and released after showing version information. 2013-03-30 01:46:56 -04:00
Nebuleon Fumika
afe9a7ca26 Fix the odd text disappearance bug in recently played games due to the position being preserved. 2013-03-30 01:22:59 -04:00
Nebuleon Fumika
55b5c8ff65 Increase the row count from 6 to 8 in the GUI, file selector and cheats. Remove the useless "dynamic cheat" functions. 2013-03-30 01:08:07 -04:00
Nebuleon Fumika
fa71ce7345 Optimise the reading of bitmap files. 2013-03-29 22:04:27 -04:00
Nebuleon Fumika
2113821e23 Fix scrollers in file selectors after the previous commit. 2013-03-29 05:52:12 -04:00
Nebuleon Fumika
efe43d2f62 Stop the odd disappearing text when moving between files in recently played games. 2013-03-29 05:45:39 -04:00
Nebuleon Fumika
9a08a7ea4a Make rendering a GUI background (256x192) more efficient. 2013-03-29 05:24:31 -04:00
Nebuleon Fumika
900aedbed8 gui.c: Overhaul the autorepeat behaviour of get_gui_input. 2013-03-29 04:41:44 -04:00
Nebuleon Fumika
4c958cf8dd Preserve the position in a menu when moving into one of its submenus. 2013-03-29 03:23:48 -04:00
Nebuleon Fumika
2237740090 Restore the functionality of selection options with handler functions. This unbreaks commit 57bcab6a25. 2013-03-28 05:02:46 -04:00
Nebuleon Fumika
9920215d94 Remove some button press/release recognition latency in the menu. 2013-03-28 04:49:31 -04:00
Nebuleon Fumika
57bcab6a25 Reduce the number of special cases in the touch handling code. 2013-03-28 04:20:29 -04:00
Nebuleon Fumika
f27122724a Fix overlapping text (screenshot creation OK/failed) in message boxes. 2013-03-28 04:03:46 -04:00
Nebuleon Fumika
8d1854d8a2 Make "Save a screenshot" work with touch. 2013-03-28 04:00:17 -04:00
Nebuleon Fumika
13449ee395 Fix a crash in the touch handler of the delete saved state submenu. 2013-03-28 02:44:51 -04:00
Nebuleon Fumika
13971bf935 Finish the back button uniformisation. 2013-03-28 02:31:17 -04:00
Nebuleon Fumika
501fe38561 Stop the path scroller flashing when moving between files in a file selector. 2013-03-28 02:19:20 -04:00
Nebuleon Fumika
dbb2dd89f0 Delete the right number of saved states when selecting one of the options. 2013-03-27 05:14:22 -04:00
Nebuleon Fumika
0b5f9ad553 "Saving state..." was still way below the top of its message box. 2013-03-27 01:35:14 -04:00
Nebuleon Fumika
639a7081d4 Use white text with a black outline when drawing the date of a saved state into its bitmap. It looks nicer than white on a rectangle of black. 2013-03-27 01:18:31 -04:00
Nebuleon Fumika
286c44077a Show the screenshot with timestamp after writing a state. 2013-03-27 01:09:27 -04:00
Nebuleon Fumika
688b13d065 Use update method 0 everywhere in the code except that double-buffered update workaround for hangs. 2013-03-27 00:37:40 -04:00
Nebuleon Fumika
b4d2fc6168 Default to the first non-Back option in all menus for which the element count is known to always be non-zero. That excludes the recently played games menu. 2013-03-26 22:29:45 -04:00
Nebuleon Fumika
a1a4c9384e Saved state menu overhaul.
* Show the screenshot of the selected saved state even in the creation and deletion rows.
* In the saved state deletion interface, make the single state deletion go first.
* The screenshot of the latest saved state or the last selected one appears when the menu loads.
* The screenshot of the paused game appears when the menu is left.
2013-03-26 22:15:26 -04:00
Nebuleon Fumika
805ccda32c Uniformise the location of the title icon across all interfaces, default and custom. 2013-03-26 19:58:17 -04:00
Nebuleon Fumika
2fd480b4f3 Uniformise the location of the back button across all interfaces, default and custom. 2013-03-26 19:53:13 -04:00
Nebuleon Fumika
577541b509 Make the Back button more visibly selected in the default skin. 2013-03-26 19:27:52 -04:00
Boriar
14e8017953 Spanish change backported from TempGBA commit 4f2205f2e554a6fa33237395c1350f194ca9308e. 2013-03-23 19:57:12 -04:00
Nebuleon Fumika
a57b91f897 Remove \r's in the basic initialisation error messages. 2013-03-23 01:21:15 -04:00
Nebuleon Fumika
362058dc00 Allocate fewer screens for the console shown when a basic initialisation error occurs. 2013-03-23 01:20:08 -04:00
Nebuleon Fumika
24b55e1c02 Release 1.33. 2013-03-20 00:35:41 -04:00
Syphurith
e35df7290c Simplified Chinese block completion. 2013-03-16 01:30:30 -04:00
Nebuleon Fumika
37ef0a9b8d Fix the text scrollers, and make the scroller code smaller to boot. 2013-03-11 00:22:01 -04:00
Nebuleon Fumika
936cb38b5e Center text without needing endless spaces; also support \n in centered text.
* Text positioning in message boxes is now controlled by #defines.
* The various MSG_PLAY_SLIDE<n> messages are now one, MSG_SCREENSHOT_SLIDESHOW_KEYS, with \n between lines.
* Use \n in some more message pairs.
* Lengthy scrollers broke. This will be investigated in a later commit.
2013-03-10 21:21:37 -04:00
Nebuleon Fumika
47a63742d7 Modified the SNES file icon not to resemble a generic controller anymore. 2013-03-07 22:10:02 -05:00
Nebuleon Fumika
1e1837c55f Add credits for language files. 2013-03-07 19:53:17 -05:00
Nebuleon Fumika
964ce2a58d Brazilian Portuguese adjustment: Frequencia da CPU -> Frequência da CPU. 2013-03-03 15:51:37 -05:00
Nebuleon Fumika
39fecc43bb Update the hotkeys preview. 2013-03-03 00:32:32 -05:00
Nebuleon Fumika
a519d9c93d Release 1.32. 2013-03-01 13:20:38 -05:00
Nebuleon Fumika
d8d2dcc959 Remove unneeded variables in draw.c. 2013-02-27 19:07:48 -05:00
Nebuleon Fumika
49cc257e8d Remove unneeded functions in draw.c. 2013-02-27 19:01:09 -05:00
Nebuleon Fumika
1c0260ecfa Define u8, s8, u16, s16, u32, s32, u64, s64 as typedefs. Ported from a test repository. 2013-02-24 18:02:55 -05:00
Nebuleon Fumika
339cdb4828 Maybe Settings.FixFrequency is what's causing the emulated SNES to be slower than a real SNES? It does an adjustment of 15/1000, after all... 2013-02-22 02:41:50 -05:00
BassAceGold
10ed45ad76 Use the CATSFC directory in the root of the storage card if a SYSTEM/GUI directory is not found in the system folder provided by plugin arguments. 2013-02-20 14:53:13 -05:00
Nebuleon Fumika
edda8744ad Start option text more to the left to fit more text in a line. Widen cheat descriptions and file names in selectors, to the left AND to the right, to make the interface consistent again (and for practical purposes). 2013-02-19 23:33:43 -05:00
Aeter
e46e351594 Dutch adjustments. Most things are shortened and aligned. 2013-02-19 18:02:35 -05:00
Diego Liberal
82c9daff5e Brazilian Portuguese adjustments.
* Frame skipping is now translated.
* Some accents were missing over "vídeo" and "áudio".
* Version information uses a better phrase.
2013-02-15 14:56:45 -05:00
Nebuleon Fumika
c2262c74c5 Release 1.31. 2013-02-14 16:36:21 -05:00
Nebuleon Fumika
52b11e6c1c Adjust hotkeys to allow using the directional pad for them. Suggested usage is L+Up, R+Up, etc. 2013-02-14 16:24:42 -05:00
Nebuleon Fumika
11c08d9d8f German adjustments, honoring GBAtemp user Charli (github: seesawCharli)'s notes on commit ea8ff33951.
Since then, pictograms for directions have been implemented and I settled on 2 spaces of spacing between a key and its description in the screenshot slideshow window.
2013-02-14 15:56:02 -05:00
Nebuleon Fumika
7dd9763658 Brazilian Portuguese adjustments.
* Align text in columns for options.
* Fix a spelling mistake, "relaizar".
* Consistency with other languages.
* Reorder the hotkey options, which I pasted in incorrectly.
2013-02-14 15:50:37 -05:00
Diego Liberal
e156b47503 Add a Brazilian Portuguese localisation. 2013-02-14 15:28:38 -05:00
Nebuleon Fumika
03e8e8863a Italian adjustments.
* Align some messages in columns.
* Make Attiva/Disattiva into (Dis)attiva to reduce the length of the fullscreen hotkey option.
* Remove "dalla card" (from the card) from "seleziona gioco" and make the title "nuovo gioco" for consistency.
* Use key pictograms in the screenshot slideshow.
2013-02-14 04:18:09 -05:00
Nebuleon Fumika
a1b2ff6e87 Merge pull request #35 from alexinfurs/master
Add an Italian translation
2013-02-14 04:05:35 -05:00
Alessandro Pelliccia
5a8a513b66 Update CATSFC/system/language.msg 2013-02-14 09:46:18 +01:00
Alessandro Pelliccia
2dcd76bced Update CATSFC/system/language.msg 2013-02-14 09:44:59 +01:00
Nebuleon Fumika
a8c2fcdb2c Add hotkeys to quickly load from and save to saved state #1, as well as to toggle full-screen (going from mode 3, middle of screen, to mode 4, full-screen smoothed).
This commit uses text that has not been validated in some languages.
2013-02-14 03:02:33 -05:00
Alessandro Pelliccia
5e10564ce0 Update source/nds/gui.c
Add Italian language
2013-02-13 21:21:08 +01:00
Alessandro Pelliccia
e7dfd96445 Update source/nds/message.h
Add Italian language
2013-02-13 21:13:29 +01:00
Alessandro Pelliccia
9b95e3c26b Update CATSFC/system/language.msg
Add an Italian translation
2013-02-13 21:10:40 +01:00
Nebuleon Fumika
6794af6695 Reimplement grouped multipart cheat codes on top of Snes9x's cheat data. 2013-02-12 00:06:39 -05:00
Nebuleon Fumika
7a2bde06a1 Language file adjustments and arrows for direction keys (*u, *d, *l, *r).
* All languages except Chinese: Remove redundancy in the New game menu. Remove "from the card".
* All languages except German and Chinese: Remove "games" in "recently played games". It's implied by the rest of the menu.
* Spanish: menu should be menú.
* All languages: modify keys in the screenshot slideshow message so that direction keys are arrows.
* Tools/Screenshots, English, French, Spanish: Stop implying that you can browse the screenshots; instead imply that it's a slideshow you control only sequentially.
* Dutch: Try to shorten "Ga terug naar het spel" so it can fit in a button, by removing the "Ga". It still splits.
2013-02-11 18:27:49 -05:00
Nebuleon Fumika
2332157879 Release 1.30. 2013-02-10 14:28:59 -05:00
Nebuleon Fumika
16a41b40b8 A type mismatch in sound channel data messed up the sound after loading a saved state in certain games. int (32 bit) is now short (16 bit). 2013-02-10 00:12:41 -05:00
Nebuleon Fumika
18e56b68fd Add retro sound as a setting in all languages except Chinese. 2013-02-09 23:41:06 -05:00
jomaper
6e2e64109d Update CATSFC/system/language.msg (Spanish block)
Hice unos cambios pequeños, nada importante, más que nada cosméticos.

I did small changes, no big deal, cosmetic stuff more than anything
2013-02-09 22:01:58 -05:00
Nebuleon Fumika
5f3a27e9e0 Merge branch '8bitsound' 2013-02-09 20:08:38 -05:00
Nebuleon Fumika
cb12547b85 Merge branch 'master' into 8bitsound 2013-02-08 19:58:41 -05:00
Nebuleon Fumika
ef12da18df Merge branch 'master' into 8bitsound 2013-02-08 17:47:20 -05:00
Nebuleon Fumika
9ef4103ea5 Add two more half-wave types to try to correct the pitch of notes that are one octave too high. 2013-02-08 16:08:48 -05:00
Nebuleon Fumika
3834297fae Fix write to uninitialised memory in 8-bit sound. 2013-02-08 15:46:33 -05:00
Nebuleon Fumika
0a2041d1ce Add square waves for waves not matching sines or triangles. Add noise for drums exceeding a certain "randomness" threshold. For now that's defined as total variance from a sample to its neighbo(u)r in a block of 16 samples. 2013-02-08 05:50:37 -05:00
Nebuleon Fumika
927d456306 Merge branch 'master' into 8bitsound
Conflicts:
	source/nds/entry.cpp
2013-02-08 05:50:22 -05:00
Nebuleon Fumika
433749b6ef Merge branch 'master' into 8bitsound 2013-01-23 20:16:46 -05:00
Nebuleon Fumika
40596a7d68 Triangle wave ALL the channels! 2013-01-21 22:35:21 -05:00
Nebuleon Fumika
7d788578b2 Initial 8-bit sound commit. For the lulz! 2013-01-20 22:26:24 -05:00
30 changed files with 3320 additions and 2293 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: 576 B

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View file

@ -0,0 +1,6 @@
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/nds/bdf_font.c source/nds/bitmap.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/gui.c source/nds/dma_adj.c source/nds/cheatgrp.c
CPP_SOURCES = source/apu.cpp source/apudebug.cpp source/c4.cpp \
source/c4emu.cpp source/cheats2.cpp source/cheats.cpp \
source/clip.cpp source/cpu.cpp source/cpuexec.cpp \

149
README.md
View file

@ -1,4 +1,4 @@
CATSFC version 1.29, 2013-02-08
CATSFC version 1.36, 2013-06-16
A Super Nintendo emulator for the Supercard DSTWO.
@ -7,55 +7,22 @@ Based on:
zsKnight, etc.)
* NDSSFC 1.06, by the Supercard team (porting to the MIPS processor)
* BAGSFC, by BassAceGold (improving over NDSSFC)
* CATSFC, by ShadauxCat (improving over BAGSFC)
* CATSFC, by ShadauxCat and Nebuleon (improving over BAGSFC)
# Compiling
(If you downloaded the plugin ready-made, you can safely skip this section.
In this case, go to `# Installing`.)
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.
Contains:
* Language files written by the GBAtemp community: Dutch by Aeter, French
by Nebuleon, German by SignZ, Portuguese (Brazilian) by Diego Liberal,
Spanish by Boriar
* Language files written by GitHub users: Italian by alexinfurs
# Installing
To install the plugin to your storage card after compiling it, copy
`catsfc.plg`, `catsfc.ini` and `catsfc.bmp` to the card's `_dstwoplug`
directory. Then, copy the source directory's CATSFC subdirectory to the
root of the card.
(If you got the source code and want to compile it, see the `Compiling` section
at the end of the file.)
To install the plugin to your storage card, copy `catsfc.plg`, `catsfc.ini` and
`catsfc.bmp` from the release archive to the card's `_dstwoplug` directory.
Then, copy the `CATSFC` subdirectory to the root of the card.
# Cheats
@ -68,14 +35,9 @@ old format used in Mightymo's BSNES Cheat Code Pack.
the operating system on your computer.
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*.
4. Open your microSD card's CATSFC folder, then descend into gamecht.
4. Open your storage card's CATSFC folder, then descend into gamecht.
5. Drag the cheat code files from the zip archive to the card's gamecht
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
menu's "Load a cheat file" option.
@ -97,7 +59,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,
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
often. The audio will also be stretched. (This is similar to NDSGBA.)
often. The audio may also be stretched. (This is similar to NDSGBA.)
* 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
perform actions during the correct frame with the DS buttons. It is advised
@ -143,10 +105,18 @@ Available actions are:
will be forced on.
* Toggle sound. Each time this hotkey is held, the sound will be disabled if
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 used by CATSFC is now similar to the Pictochat font. To modify it,
The font used by CATSFC is similar to the Pictochat font. To modify it,
see `source/font/README.txt`.
# Translations
@ -158,40 +128,87 @@ need to do the following:
* Open `CATSFC/system/language.msg`.
* Copy what's between `STARTENGLISH` and `ENDENGLISH` and paste it at the end
of the file.
* Change the tags. For example, if you want to translate to German, the tags
will become `STARTGERMAN` and `ENDGERMAN`.
* Change the tags. For example, if you want to translate to Japanese, the tags
will become `STARTJAPANESE` and `ENDJAPANESE`.
* Translate each of the messages, using the lines starting with `#MSG_` as a
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
language there. For the example of German, you would add this at the end of
language there. For the example of Japanese, you would add this at the end of
the list:
```
,
GERMAN
JAPANESE
```
* Still in `source/nds/message.h`, just below `enum LANGUAGE`, you will find
`extern char* lang[` *some number* `]`. Add 1 to that 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
German, you would add this at the end of the list:
Japanese, you would add this at the end of the list:
```
,
"Deutsch"
"日本語"
```
* 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
plus 1. For example, if the last entry is `, (char *) &lang[2]`, yours would
be `, (char *) &lang[3]`.
plus 1. For example, if the last entry is `, (char *) &lang[7]`, yours would
be `, (char *) &lang[8]`.
* Still in `source/nds/gui.c`, find `case CHINESE_SIMPLIFIED`. Copy the lines
starting at the `case` and ending with `break`, inclusively. Paste them
before the `}`. Change the language name and tags. For the example of
German, you would use:
Japanese, you would use:
```
case GERMAN:
strcpy(start, "STARTGERMAN");
strcpy(end, "ENDGERMAN");
case JAPANESE:
strcpy(start, "STARTJAPANESE");
strcpy(end, "ENDJAPANESE");
break;
```
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!
# 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,37 +1,29 @@
#ifndef __DS2_TYPES_H__
#define __DS2_TYPES_H__
#ifndef u8
#define u8 unsigned char
#endif
typedef unsigned char u8;
typedef char s8;
#ifndef s8
#define s8 char
#endif
typedef unsigned short u16;
typedef short s16;
#ifndef u16
#define u16 unsigned short
#endif
typedef unsigned int u32;
typedef int s32;
#ifndef s16
#define s16 short
#endif
typedef unsigned long long u64;
typedef long long s64;
#ifndef u32
#define u32 unsigned int
#endif
typedef volatile unsigned char vu8;
typedef volatile char vs8;
#ifndef s32
#define s32 int
#endif
typedef volatile unsigned short vu16;
typedef volatile short vs16;
#ifndef u64
#define u64 unsigned long long
#endif
typedef volatile unsigned int vu32;
typedef volatile int vs32;
#ifndef s64
#define s64 long long
#endif
typedef volatile unsigned long long vu64;
typedef volatile long long vs64;
#ifndef NULL
#define NULL 0

View file

@ -49,9 +49,10 @@
#define BYTES_PER_READ 512
#ifndef NULL
#define NULL 0
#endif
// MODIFICATION START [Neb]
// In libfat by Chishm, some types are #define'd here. In the DS2 SDK,
// these types are defined by another header.
#include "ds2_types.h"
#ifndef bool
#define bool int
@ -65,21 +66,7 @@
#define true 1
#endif
#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
// MODIFICATION END [Neb]
struct _reent
{

View file

@ -135,7 +135,7 @@ bool _FAT_directory_isValidLfn (const char* name) {
return true;
}
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 nameLength;
@ -159,7 +159,7 @@ bool _FAT_directory_isValidAlias (const char* name) {
// Make sure the name doesn't contain any control codes
//if name isn't all capitals, then it is not a valid short name
for (i = 0; i < nameLength; i++) {
if (name[i] < 0x5A && name[i]!=0x20) {
if (name[i] > 0x5A && name[i]!= 0x20) {
return false;
}
}
@ -756,7 +756,37 @@ static bool _FAT_directory_entryExists (PARTITION* partition, const char* name,
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) {
u32 entrySize;
@ -833,7 +863,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu
++ j;
}
// Short filename
strupr (entry->d_name);
strupr (entry->entryData);
}else {
// Long filename needed
//memset( entry->unicodeFilename, 0, 512 );
@ -883,7 +913,7 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, u32 dirClu
i++;
alias[6] = '0' + ((i / 10) % 10); // 10's digit
alias[7] = '0' + (i % 10); // 1's digit
} while (_FAT_directory_entryExists (partition, alias, dirCluster) && (i < 100));
} while (_FAT_directory_entryExistsSFN (partition, alias, dirCluster) && (i < 100));
if (i == 100) {
// Couldn't get a tail number
return false;

View file

@ -49,9 +49,10 @@
#define BYTES_PER_READ 512
#ifndef NULL
#define NULL 0
#endif
// MODIFICATION START [Neb]
// In libfat by Chishm, some types are #define'd here. In the DS2 SDK,
// these types are defined by another header.
#include "ds2_types.h"
#ifndef bool
#define bool int
@ -65,21 +66,7 @@
#define true 1
#endif
#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
// MODIFICATION END [Neb]
struct _reent
{

View file

@ -101,8 +101,7 @@ struct SCheat
uint32 address;
uint8 byte;
uint8 saved_byte;
// bool8 enabled;
u32 enabled; // THIS IS A TOTAL HACK FOR THE NDSSFC GUI, YOU HAVE BEEN WARNED [Neb]
bool8 enabled;
bool8 saved;
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
- direction 0: count UNICODE charactor numbers in width pixels, from front
- direction 1: count UNICODE charactor numbers in width pixels, from end
- direction 0: count UNICODE charactor numbers in width pixels, from end
- direction 1: count UNICODE charactor numbers in width pixels, from front
- direction 2: conut total pixel width of len UNICODE charachtors, from end
- 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 i, xw, num;
u32 i, lastSpace = 0, xw, num;
u16 unicode;
u32 start, end;
struct bdffont *bdf_fontp[2];
@ -1049,14 +1049,19 @@ u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
while(len > 0)
{
unicode= unicodes[i];
if (unicode == 0x0A)
return num - len;
else if (unicode == ' ')
lastSpace = len;
xw += BDF_width16_ucs(unicode);
if(xw >= width) break;
if(xw > width) return num - lastSpace;
i += direction;
len--;
}
num -= len;
return num - len;
}
else
{
@ -1073,9 +1078,9 @@ u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
}
num= xw;
}
return num;
}
}

View file

@ -20,6 +20,7 @@
#include "fs_api.h"
#include "bitmap.h"
#include "ds2_malloc.h"
int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height, unsigned int* type)
{
@ -59,16 +60,22 @@ 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.imImcolnum= st[25] | (st[26]<<16);
if(bmp_header.bfType != 0x4D42) //"BM"
if(bmp_header.bfType != 0x4D42) { //"BM"
fclose(fp);
return BMP_ERR_FORMATE;
}
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...
}
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...
}
*type = bytepixel;
@ -81,16 +88,29 @@ int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height,
if(y > sy)
y= sy;
//BMP scan from down to up
fpos= (s32)bmp_header.bfImgoffst;
dest= (unsigned char*)buf+(y-1)*x*bytepixel;
for(m= 0; m < y; m++) {
fseek(fp, fpos, SEEK_SET);
fread(dest, 1, x*bytepixel, fp);
fpos += ((sx*bytepixel+3)>>2)<<2;
dest -= x*bytepixel;
// Expect a certain amount of bytes and read them all at once.
unsigned int BytesPerLine = (sx * bytepixel + 3) & ~3;
char* FileBuffer = (char*) malloc(BytesPerLine * (sy - 1) + sx * bytepixel);
if (FileBuffer == NULL) {
fclose(fp);
return BMP_ERR_NEED_GO_ON; // Memory allocation error
}
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);
return BMP_OK;

100
source/nds/cheatgrp.c Normal file
View file

@ -0,0 +1,100 @@
/* 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;
}

27
source/nds/cheatgrp.h Normal file
View file

@ -0,0 +1,27 @@
/* 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 NDSSFCDrawFrameAntialiased (void* screen_addr)
{
uint16 X, Y;
uint16 *SrcTop = (uint16 *) GFX.Screen, *SrcBottom = SrcTop + 256, *Dest = (uint16 *) up_screen_addr;
uint16 *SrcTop = (uint16 *) GFX.Screen, *SrcBottom = SrcTop + 256, *Dest = (uint16 *) screen_addr;
for (Y = 0; Y < 224; Y += 7)
{

View file

@ -58,10 +58,6 @@
#define GUI_SOURCE_PATH "SYSTEM/GUI"
#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];
struct gui_iconlist gui_icon_list[]= {
@ -110,6 +106,13 @@ struct gui_iconlist gui_icon_list[]= {
/* 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
@ -302,7 +305,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));
// drawboxfill(screen_addr, sx+1, sy+1, ex-1, ey-1, color_fg);
show_icon(screen_addr, &ICON_MSG, 34, 48);
show_icon(screen_addr, &ICON_MSG, (NDS_SCREEN_WIDTH - ICON_MSG.x) / 2, (NDS_SCREEN_HEIGHT - ICON_MSG.y) / 2);
}
else
{
@ -348,29 +351,27 @@ void draw_string_vcenter(void* screen_addr, u32 sx, u32 sy, u32 width, u32 color
while(*string)
{
string= utf8decode(string, unicode+num);
if(unicode[num] != 0x0D && unicode[num] != 0x0A) num++;
num++;
}
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;
i= 0;
while(i < num)
{
m= BDF_cut_unicode(&unicode[i], num-i, width, 1);
x= 0;
x= (width - BDF_cut_unicode(&unicode[i], m, 0, 3)) / 2;
while(m--)
{
x += BDF_render16_ucs(screenp+x, SCREEN_WIDTH, 0, COLOR_TRANS,
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;
}
}
@ -408,12 +409,29 @@ struct scroll_string_info{
static struct scroll_string_info scroll_strinfo[MAX_SCROLL_STRING];
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 index, x, num, len, i;
u32 index, x, textWidth, num, len, i;
u16 *unicode, *screenp;
// 1. Which scroller should we use for this request?
for(i= 0; i < MAX_SCROLL_STRING; i++)
{
if(scroll_strinfo[i].screenp == NULL)
@ -424,23 +442,39 @@ u32 draw_hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
return -1;
index= i;
screenp= (u16*)malloc((256+128)*FONTS_HEIGHT*2);
if(screenp == NULL)
{
scroll_strinfo[index].str_len = 0;
return -2;
}
unicode= (u16*)malloc(256*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;
free((void*)screenp);
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)
{
scroll_strinfo[index].str_len = 0;
free((void*)unicode);
return -2;
}
if(color_bg == COLOR_TRANS)
memset(screenp, 0, (256+128)*FONTS_HEIGHT*2);
memset(screenp, 0, textWidth*FONTS_HEIGHT*sizeof(u16));
scroll_string_num += 1;
scroll_strinfo[index].screenp = (unsigned short*)screen_addr;
@ -453,208 +487,81 @@ u32 draw_hscroll_init(void* screen_addr, u32 sx, u32 sy, u32 width,
scroll_strinfo[index].unicode= unicode;
scroll_strinfo[index].buff_fonts= screenp;
scroll_strinfo[index].buff_bg= 0;
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].buff_width= textWidth;
scroll_strinfo[index].pos_pixel= 0;
scroll_strinfo[index].str_start= 0;
scroll_strinfo[index].str_end= len-1;
num= scroll_strinfo[index].height;
len= width;
scroll_strinfo[index].str_len= num;
if(num == 0)
return index; // (1. Which scroller?)
u16 *screenp1;
if(color_bg == COLOR_TRANS)
// 4. Render text into the allocation.
i= 0;
x= 0;
while(i < num)
{
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);
}
x += BDF_render16_ucs(screenp + x, textWidth, 0, color_bg, color_fg, unicode[i++]);
}
return index;
return index; // (1. Which scroller?)
}
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 color_bg, color_fg, i, width, height;
s32 xoff;
//static int flag= 0;
if(index >= MAX_SCROLL_STRING) return -1;
if(scroll_strinfo[index].screenp == NULL) return -2;
if(scroll_strinfo[index].str_len == 0) return 0;
width= scroll_strinfo[index].width;
height= scroll_strinfo[index].height;
xoff= scroll_strinfo[index].pos_pixel - scroll_val;
color_bg= scroll_strinfo[index].color_bg;
color_fg= scroll_strinfo[index].color_fg;
if(scroll_val > 0) //shift right
{
if(xoff <= 0)
{
if(scroll_strinfo[index].str_start > 0)
{
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))
// 1. Shift the scroller.
scroll_strinfo[index].pos_pixel -= scroll_val;
if (scroll_strinfo[index].pos_pixel < 0) // Reached the beginning
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;
else if (scroll_strinfo[index].pos_pixel > scroll_strinfo[index].buff_width - width) // Reached the end
scroll_strinfo[index].pos_pixel = scroll_strinfo[index].buff_width - width;
// 2. Draw the scroller's text at its new position.
u32 x, sx, sy, pixel;
u16 *screenp, *screenp1;
color_bg = scroll_strinfo[index].color_bg;
sx= scroll_strinfo[index].sx;
sy= scroll_strinfo[index].sy;
@ -663,7 +570,7 @@ u32 draw_hscroll(u32 index, s32 scroll_val)
for(i= 0; i < height; i++)
{
screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts + xoff + i*(256+128);
screenp1= scroll_strinfo[index].buff_fonts + scroll_strinfo[index].pos_pixel + i*scroll_strinfo[index].buff_width;
for(x= 0; x < width; x++)
{
pixel= *screenp1++;
@ -677,19 +584,21 @@ u32 draw_hscroll(u32 index, s32 scroll_val)
for(i= 0; i < height; i++)
{
screenp= scroll_strinfo[index].screenp + sx + (sy + i) * SCREEN_WIDTH;
screenp1= scroll_strinfo[index].buff_fonts + xoff + i*(256+128);
screenp1= scroll_strinfo[index].buff_fonts + scroll_strinfo[index].pos_pixel + i*scroll_strinfo[index].buff_width;
for(x= 0; x < width; x++)
*screenp++ = *screenp1++;
}
}
u32 ret;
// 3. Return how many more pixels we can scroll in the same direction.
if(scroll_val > 0)
ret= scroll_strinfo[index].pos_pixel;
// Scrolling to the left: Return the number of pixels we can still go
// to the left.
return scroll_strinfo[index].pos_pixel;
else
ret= scroll_strinfo[index].buff_width - scroll_strinfo[index].pos_pixel;
return ret;
// Scrolling to the right: Return the number of pixels we can still go
// to the right.
return scroll_strinfo[index].buff_width - scroll_strinfo[index].pos_pixel - width;
}
void draw_hscroll_over(u32 index)
@ -719,6 +628,7 @@ void draw_hscroll_over(u32 index)
/*
* Drawing dialog
*/
/*
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);
@ -745,6 +655,7 @@ void draw_dialog(void* screen_addr, u32 sx, u32 sy, u32 ex, u32 ey)
drawboxfill(screen_addr, sx, sy, ex, ey, COLOR_DIALOG);
}
*/
/*
* Draw yes or no dialog
@ -791,13 +702,16 @@ u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no)
else
screen_addr = down_screen_addr;
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);
sy = (NDS_SCREEN_HEIGHT + ICON_MSG.y) / 2 - 8 - ICON_BUTTON.y;
i= SCREEN_WIDTH/2 + 3;
show_icon((unsigned short*)screen_addr, &ICON_BUTTON, 136, 128);
draw_string_vcenter((unsigned short*)screen_addr, 138, 130, 73, COLOR_WHITE, no);
u32 left_sx = NDS_SCREEN_WIDTH / 2 - 8 - ICON_BUTTON.x,
right_sx = NDS_SCREEN_WIDTH / 2 + 8;
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);
@ -810,11 +724,11 @@ u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no)
struct key_buf inputdata;
ds2_getrawInput(&inputdata);
// Turn it into a SELECT (A) or BACK (B) if the button is touched.
if (inputdata.y >= 128 && inputdata.y < 128 + ICON_BUTTON.y)
if (inputdata.y >= sy && inputdata.y < sy + ICON_BUTTON.y)
{
if (inputdata.x >= 49 && inputdata.x < 49 + ICON_BUTTON.x)
if (inputdata.x >= left_sx && inputdata.x < left_sx + ICON_BUTTON.x)
gui_action = CURSOR_SELECT;
else if (inputdata.x >= 136 && inputdata.x < 136 + ICON_BUTTON.x)
else if (inputdata.x >= right_sx && inputdata.x < right_sx + ICON_BUTTON.x)
gui_action = CURSOR_BACK;
}
}
@ -898,12 +812,11 @@ 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
// 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.
// Also ignore the direction pad because every game uses it.)
// touching to get to the menu will do stuff the user doesn't expect.)
u32 TotalKeys = 0;
do {
TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID | KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT);
TotalKeys |= inputdata.key & ~(KEY_TOUCH | KEY_LID);
// If there's a touch on either button, turn it into a
// clear (A) or cancel (B) request.
if (inputdata.key & KEY_TOUCH)
@ -923,93 +836,6 @@ u32 draw_hotkey_dialog(enum SCREEN_ID screen, u32 sy, char *clear, char *cancel)
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
*/
@ -1281,6 +1107,62 @@ int icon_init(u32 language_id)
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)
{
@ -1291,6 +1173,13 @@ void show_icon(void* screen, struct gui_iconlist* icon, u32 x, u32 y)
dst = (unsigned short*)screen + y*NDS_SCREEN_WIDTH + x;
if(NULL == src) return; //The icon may initialized failure
if (icon->x == NDS_SCREEN_WIDTH && icon->y == NDS_SCREEN_HEIGHT && x == 0 && y == 0)
{
// Don't support transparency for a background.
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++)
@ -1302,6 +1191,7 @@ void show_icon(void* screen, struct gui_iconlist* icon, u32 x, u32 y)
dst += NDS_SCREEN_WIDTH;
}
}
}
/*************************************************************/
void show_Vscrollbar(char *screen, u32 x, u32 y, u32 part, u32 total)
@ -1373,7 +1263,7 @@ void show_log(void* screen_addr)
void err_msg(enum SCREEN_ID screen, char *msg)
{
// A wild console appeared!
ConsoleInit(RGB15(31, 31, 31), RGB15(0, 0, 0), UP_SCREEN, 512);
ConsoleInit(RGB15(31, 31, 31), RGB15(0, 0, 0), UP_SCREEN, 2);
printf(msg);
}

View file

@ -61,27 +61,25 @@
#define COLOR_TRANS COLOR16(31, 31, 63)
#define COLOR_WHITE COLOR16(31, 31, 31)
#define COLOR_BLACK COLOR16( 0, 0, 0)
#define COLOR_TEXT COLOR16(31, 31, 31)
#define COLOR_PROGRESS_TEXT COLOR16( 0, 0, 0)
#define COLOR_PROGRESS_BAR COLOR16(15, 15, 15)
#define COLOR_ERROR COLOR16(31, 0, 0)
#define COLOR_BG COLOR16(2, 4, 10)
#define COLOR_BG32 COLOR32(2*8, 4*8, 10*8)
#define COLOR_ROM_INFO COLOR16(22, 18, 26)
#define COLOR_ACTIVE_ITEM COLOR16(31, 31, 31)
#define COLOR_INACTIVE_ITEM COLOR16(11, 7, 19)
#define COLOR_HELP_TEXT COLOR16(16, 20, 24)
#define COLOR_DIALOG COLOR16(31, 31, 31)
#define COLOR_DIALOG_SHADOW COLOR16( 0, 2, 8)
#define COLOR_FRAME COLOR16( 0, 0, 0)
#define COLOR_YESNO_TEXT COLOR16( 0, 0, 0)
#define COLOR_GREEN COLOR16( 0, 31, 0 )
#define COLOR_GREEN1 COLOR16( 0, 24, 0 )
#define COLOR_GREEN2 COLOR16( 0, 18, 0 )
#define COLOR_GREEN3 COLOR16( 0, 12, 0 )
#define COLOR_GREEN4 COLOR16( 0, 6, 0 )
#define COLOR_RED COLOR16( 31, 0, 0 )
#define COLOR_MSSG COLOR16( 16, 8, 29)
//#define COLOR_TEXT COLOR16(31, 31, 31)
//#define COLOR_PROGRESS_TEXT COLOR16( 0, 0, 0)
//#define COLOR_PROGRESS_BAR COLOR16(15, 15, 15)
//#define COLOR_ERROR COLOR16(31, 0, 0)
//#define COLOR_BG COLOR16(2, 4, 10)
//#define COLOR_BG32 COLOR32(2*8, 4*8, 10*8)
//#define COLOR_ROM_INFO COLOR16(22, 18, 26)
//#define COLOR_HELP_TEXT COLOR16(16, 20, 24)
//#define COLOR_DIALOG COLOR16(31, 31, 31)
//#define COLOR_DIALOG_SHADOW COLOR16( 0, 2, 8)
//#define COLOR_FRAME COLOR16( 0, 0, 0)
//#define COLOR_YESNO_TEXT COLOR16( 0, 0, 0)
//#define COLOR_GREEN COLOR16( 0, 31, 0 )
//#define COLOR_GREEN1 COLOR16( 0, 24, 0 )
//#define COLOR_GREEN2 COLOR16( 0, 18, 0 )
//#define COLOR_GREEN3 COLOR16( 0, 12, 0 )
//#define COLOR_GREEN4 COLOR16( 0, 6, 0 )
//#define COLOR_RED COLOR16( 31, 0, 0 )
//#define COLOR_MSSG COLOR16( 16, 8, 29)
/******************************************************************************
*
******************************************************************************/
@ -89,6 +87,13 @@
extern "C" {
#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{
char bgname[128];
char bgbuffer[256*192*2];
@ -161,15 +166,14 @@ 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,
u32 color_fg, char *string);
#define MAX_SCROLL_STRING 8
#define MAX_SCROLL_STRING 16
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,
u32 color_bg, u32 color_fg, char *string);
extern u32 draw_hscroll(u32 index, s32 scroll_val);
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 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 u32 yesno_dialog(char *text);
extern u32 draw_yesno_dialog(enum SCREEN_ID screen, u32 sy, char *yes, char *no);
@ -181,6 +185,7 @@ extern void msg_screen_clear(void);
extern void msg_set_text_color(u32 color);
extern int icon_init(u32 language_id);
extern int color_init(void);
extern int gui_change_icon(u32 language_id);
extern int show_background(void *screen, char *bgname);
extern void show_icon(void* screen, struct gui_iconlist *icon, u32 x, u32 y);

View file

@ -33,6 +33,12 @@ void S9xProcessSound (unsigned int);
char *rom_filename = 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];
#define FIXED_POINT 0x10000
@ -134,22 +140,29 @@ bool8 S9xInitUpdate ()
}
extern void NDSSFCDrawFrameAntialiased();
extern void NDSSFCDrawFrameAntialiased(void* screen_addr);
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)
{
//Up
case 1:
#ifdef DS2_DMA
__dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2);
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2);
ds2_DMA_wait(1);
ds2_DMA_stop(1);
#else
memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2);
memcpy(screen_addr, GFX.Screen+256*32*2, 256*192*2);
#endif
break;
@ -157,11 +170,11 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
case 2:
#ifdef DS2_DMA
__dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2);
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen, 256 * 192 * 2);
ds2_DMA_wait(1);
ds2_DMA_stop(1);
#else
memcpy(up_screen_addr, GFX.Screen, 256*192*2);
memcpy(screen_addr, GFX.Screen, 256*192*2);
#endif
break;
@ -169,16 +182,16 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
case 3:
#ifdef DS2_DMA
__dcache_writeback_all();
ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2);
ds2_DMAcopy_32Byte(1 /* channel: graphics */, screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2);
ds2_DMA_wait(1);
ds2_DMA_stop(1);
#else
memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2);
memcpy(screen_addr, GFX.Screen+256*16*2, 256*192*2);
#endif
break;
case 4:
NDSSFCDrawFrameAntialiased ();
NDSSFCDrawFrameAntialiased (screen_addr);
break;
@ -191,7 +204,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
register unsigned int m;
src = GFX.Screen;
dst = (unsigned char*)up_screen_addr;
dst = (unsigned char*)screen_addr;
for(m = 0; m < 32; m++)
{
#ifdef DS2_DMA
@ -208,7 +221,7 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
break;
}
ds2_flipScreen(UP_SCREEN, UP_SCREEN_UPDATE_METHOD);
ds2_flipScreen(screen_num, UP_SCREEN_UPDATE_METHOD);
// 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
// frame. With update method 0, this is mitigated. (Method 2 is too slow.)
@ -406,6 +419,20 @@ 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)
{
ZeroMemory (&Settings, sizeof (Settings));
@ -424,8 +451,7 @@ void init_sfc_setting(void)
Settings.DisableSoundEcho = FALSE;
//sound settings
Settings.APUEnabled = Settings.NextAPUEnabled = TRUE;
Settings.FixFrequency = 1;
Settings.InterpolatedSound = TRUE;
// Settings.FixFrequency = 1;
Settings.H_Max = SNES_CYCLES_PER_SCANLINE;
Settings.SkipFrames = AUTO_FRAMERATE;
@ -613,17 +639,41 @@ int sfc_main (int argc, char **argv)
}
else
#endif
{
if (SaveStateNeeded) {
QuickSaveState ();
SaveStateNeeded = FALSE;
}
if (LoadStateNeeded) {
QuickLoadState ();
LoadStateNeeded = FALSE;
}
if (Settings.Paused)
{
S9xSetSoundMute (TRUE);
unsigned short screen[256*192];
copy_screen((void*)screen, up_screen_addr, 0, 0, 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
//if (Settings.JoystickEnabled && (JoypadSkip++ & 1) == 0)
@ -645,7 +695,6 @@ void S9xSyncSpeed ()
{
uint32 syncnow;
int32 syncdif;
unsigned int LastAutoCPUFrequency = AutoCPUFrequency;
#if 0
if (Settings.SoundSync == 2)
@ -1184,6 +1233,9 @@ const unsigned int keymap[12] = {
*/
static bool8 SoundToggleWasHeld = FALSE;
static bool8 LoadStateWasHeld = FALSE;
static bool8 SaveStateWasHeld = FALSE;
static bool8 ToggleFullScreenWasHeld = FALSE;
#ifdef ACCUMULATE_JOYPAD
// These are kept as DS key bitfields until it's time to send them to Snes9x.
@ -1229,16 +1281,22 @@ uint32 S9xReadJoypad (int which1)
mdelay(1);
} while (inputdata.key & KEY_LID);
ds2_wakeup();
// Before starting to emulate again, turn off the lower
// screen's backlight.
// Before starting to emulate again, turn on only the
// game screen's backlight.
SCREEN_ID screen_num = emu_config.BottomScreenGame
? DOWN_SCREEN
: UP_SCREEN;
mdelay(100); // needed to avoid ds2_setBacklight crashing
ds2_setBacklight(2);
ds2_setBacklight(3 - screen_num);
GameFrequencyCPU();
}
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 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 ||
(HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu))
@ -1261,6 +1319,37 @@ uint32 S9xReadJoypad (int which1)
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
// DS -> SNES

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,46 @@
#define UP_SCREEN_UPDATE_METHOD 0
#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
#ifdef __cplusplus
@ -43,7 +83,11 @@ struct _EMU_CONFIG
u32 HotkeyReturnToMenu;
u32 HotkeyTemporaryFastForward;
u32 HotkeyToggleSound;
u32 Reserved[61];
u32 HotkeyQuickLoadState;
u32 HotkeyQuickSaveState;
u32 HotkeyToggleFullScreen;
u32 BottomScreenGame;
u32 Reserved[57];
};
struct _GAME_CONFIG
@ -72,7 +116,11 @@ struct _GAME_CONFIG
* THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0.
*/
u32 PreviouslyUsed_20130206_2;
u32 Reserved2[42];
u32 RetroSound;
u32 HotkeyQuickLoadState;
u32 HotkeyQuickSaveState;
u32 HotkeyToggleFullScreen;
u32 Reserved2[38];
};
typedef enum
@ -116,7 +164,6 @@ extern char main_path[MAX_PATH];
extern char rom_path[MAX_PATH];
extern u32 game_enable_audio;
extern u32 clock_speed_number;
extern u32 game_fast_forward;
extern u32 temporary_fast_forward;
@ -138,12 +185,14 @@ extern GAME_CONFIG game_config;
******************************************************************************/
extern void gui_init(u32 lang_id);
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 HighFrequencyCPU();
extern void GameFrequencyCPU();
extern void QuickSaveState();
extern void QuickLoadState();
extern void ToggleFullScreen();
extern int load_language_msg(char *filename, u32 language);
#ifdef __cplusplus

View file

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

View file

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

View file

@ -168,6 +168,19 @@ extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *);
#define LAST_SAMPLE 0xffffff
#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)
{
uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff);
@ -819,6 +832,195 @@ void DecodeBlock (Channel *ch)
ch->block = ch->decoded;
return;
}
if (Settings.EightBitConsoleSound)
{
signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
filter = *compressed;
if ((ch->last_block = filter & 1))
ch->loop = (filter & 2) != 0;
int16 interim[16];
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);
noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1);
ch->decoded[i] = (noise_gen << 17) >> 17;
}
}
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])
{
/* 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
{
signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
filter = *compressed;
@ -885,7 +1087,7 @@ void DecodeBlock (Channel *ch)
}
ch->previous [0] = prev0;
ch->previous [1] = prev1;
}
ch->block_pointer += 9;
}

View file

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