Skip to content

Commit

Permalink
✨ Implement remove game feature (#9)
Browse files Browse the repository at this point in the history
* ✨ Implement remove game feature

* 🐛 Fix translation of success msg and category reset when lang changed
  • Loading branch information
dev-drprasad authored Feb 2, 2021
1 parent 850da6d commit 12c9f4f
Show file tree
Hide file tree
Showing 19 changed files with 425 additions and 100 deletions.
10 changes: 10 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
- `classics_menu_ok.drm` (Not sure from which console) and `Menu.ocv` (from Y2) have same music. But their content is different though
- Files that starts with `SP_ToneMaker`/`SPF2ALP` contains music/sound
- I assumed `Menu.ocv` contains PCM raw data and played with audacity (8bit unsinged, Mono, saample rate: 22050), I hear music, but there is too much noise. Either my settings are wrong or its not PCM
- G+ gadget audio file batch converter can be used to make "data frog Y2" supported music.
- [Download](https://www.generalplus.com/1LVlangLNxxSVyySNservice_n_support_d)
- Alogirthm: H/W PCM 16-Bit (DRM)
- I tried with sample rates: 22050, 11025 wav input files
- Output drm file more than 3MB didn't work for me

### REFERENCES

Expand All @@ -22,3 +27,8 @@
- https://github.com/alito/mamele/commit/d4ce622200de7a3b2088524e8798324c890b781b
- https://github.com/search?p=2&q=adpcm36+decoding&type=Code
- https://github.com/Jeija/bluefluff
- https://sites.google.com/site/devusb/waveformat
- http://webcache.googleusercontent.com/search?q=cache:QPxE2Hil8_wJ:bootleg.games/BGC_Forum/index.php%3Faction%3Dprofile%3Barea%3Dshowposts%3Bsa%3Dtopics%3Bu%3D38
- online-convert.com
- https://hackmii.com/2010/04/sunplus-the-biggest-chip-company-youve-never-heard-of/
- https://www.dl-sounds.com/royalty-free
17 changes: 17 additions & 0 deletions debugging.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,20 @@ narrator02 53505F54 6F6E654D 616B6572 00F31200 112B0000 C72B0000 00000000 0
narrator07 53505F54 6F6E654D 616B6572 00F31200 112B0000 C72B0000 00000000 00000000 05000000 00000000 22376 (11207)
whistle wav:
5C307200 57415645 666D7420 10000000 01000100 80BB0000 00770100 02001000 63756520 34000000

A3600 ADPCM36 💥
A4800 (with event) probably not
A6400 probably not
ADPCM36 DRM 💥
ADPCM66 💥
H/W ADPCM (A340640) just constant sound
H/W ADPCM (DRM) weird sound (high speed ???) (with 8uint resolution,8uint PCM,22050 sample rate 1 first iteration works)
H/W PCM (A340640) 💥
h/W PCM (GPFA) weird sound (high speed ???)
H/W PCM 16-Bit constant sound
H/W PCM 16-Bit (DRM) (works 8uint resolution,8uint PCM,22050 sample rate 1)

Good Music:
Chrono Trigger OST - 12 Battle
Chrono Trigger OST - 31 Bike Chase
Chrono Trigger OST - 32 Robo's Theme
2 changes: 1 addition & 1 deletion frontend/package.json.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
befffd863be894f9d2020ecf996aa7d3
91d42f500b55f4558761a99b0a09d77d
82 changes: 48 additions & 34 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import Alert from "./Alert";
import GitHubIcon from "./GitHubIcon";
import { ReactComponent as Spinner } from "./spinner.svg";
import { useTranslation } from "react-i18next";
import GameList from "./GameList";
const initialState = {
rootDir: "",
modified: false,
games: [],
newGames: [],
categoryID: -1,
errors: { rootDir: "" },
message: undefined,
Expand All @@ -21,7 +21,7 @@ const gameSorter = (a, b) => a.name.localeCompare(b.name);
function App() {
const { t, i18n } = useTranslation("translation");
const [state, setState] = useState(initialState);
const { rootDir, newGames, games, categoryID, errors, message, modified, saving } = state;
const { rootDir, games, categoryID, errors, message, modified, saving } = state;

const handleSelectRootClick = () => {
window.backend.Runtime.SelectRootDir().then((selectedDir) => {
Expand All @@ -32,15 +32,15 @@ function App() {
const handleSelectGamesClick = (e) => {
window.backend.Runtime.SelectGames()
.then((selected) => {
console.log("selected :>> ", selected);
const temp = [...newGames, ...selected];
const temp = [...games, ...selected];
console.log("temp :>> ", temp);
let seen = {};
const newGamesSet = [];
temp.forEach((g) => {
if (!seen[g.srcPath]) newGamesSet.push((seen[g.srcPath] = g));
if (!(g.srcPath && seen[g.srcPath])) newGamesSet.push((seen[g.srcPath] = g));
});
seen = undefined;
setState((s) => ({ ...s, modified: true, newGames: newGamesSet }));
setState((s) => ({ ...s, modified: true, games: newGamesSet.sort(gameSorter) }));
})
.catch(setError);
};
Expand Down Expand Up @@ -74,7 +74,7 @@ function App() {
...s,
modified: false,
newGames: [],
games: games,
games: games.sort(gameSorter),
message: undefined,
}));
})
Expand All @@ -85,6 +85,16 @@ function App() {
window.backend.Runtime.OpenURL("https://github.com/dev-drprasad/hsk00/");
};

const handleGameToggleDelete = (id) => () => {
const g = { ...games[id], deleted: !games[id].deleted };
if (g.hsk) {
setState((s) => ({ ...s, modified: true, games: [...games.slice(0, id), g, ...games.slice(id + 1)] }));
} else {
// this is unsaved game, delete this from list
setState((s) => ({ ...s, modified: true, games: [...games.slice(0, id), ...games.slice(id + 1)] }));
}
};

const handleSubmit = () => {
const errors = {};
if (!rootDir) {
Expand All @@ -93,17 +103,15 @@ function App() {
if (categoryID < 0) {
errors["categoryID"] = "select category";
}
if (newGames.length === 0) {
errors["newGames"] = "select game(s) to add";
}

if (errors.length > 0) {
setState((s) => ({ ...s, errors: errors }));
return;
} else {
setState((s) => ({ ...s, saving: true, errors: {} }));
setState((s) => ({ ...s, saving: true, message: undefined, errors: {} }));
}
console.log("rootDir, categoryID, newGames :>> ", rootDir, categoryID, newGames);
window.backend.Runtime.AddGames(rootDir, categoryID, newGames)
console.log("rootDir, categoryID, newGames :>> ", rootDir, categoryID, games);
window.backend.Runtime.Save(rootDir, categoryID, games)
.then((res) => {
setState((s) => ({
...s,
Expand All @@ -113,14 +121,24 @@ function App() {
saving: false,
message: {
type: "success",
content: `🎉 ${newGames.length} ` + t("game(s) added successfully!") + ` 🎉`,
content: "🎉 " + t("Changes saved successfully!") + " 🎉",
},
}));
})
.catch(setError);
};

const allgames = [...games, ...newGames].sort(gameSorter);
// const allgames = [...games, ...newGames].sort(gameSorter);
const newGamesCount = games.filter(({ hsk }) => !hsk).length;
const deletedGamesCount = games.filter(({ deleted }) => !!deleted).length;

let totalGamesLabel = "";
if (games.length > 0) {
totalGamesLabel = `${games.length - newGamesCount}`;
if (newGamesCount) totalGamesLabel += ` + ${newGamesCount}`;
if (deletedGamesCount) totalGamesLabel += ` - ${deletedGamesCount}`;
totalGamesLabel = `(${totalGamesLabel})`;
}

useEffect(() => {
if (rootDir && categoryID > -1) {
Expand All @@ -129,13 +147,13 @@ function App() {
}, [rootDir, categoryID, refreshGameList]);

const categoryOptions = [
t("Action Game"),
t("Shoot Game"),
t("Sport Game"),
t("Fight Game"),
t("Racing Game"),
t("Puzzle Game"),
].map((c, i) => ({ label: `${i}. ${c}`, value: i }));
"Action Game",
"Shoot Game",
"Sport Game",
"Fight Game",
"Racing Game",
"Puzzle Game",
].map((c, i) => ({ label: `${t("Category")} ${i + 1} (${c})`, value: i }));

return (
<React.Fragment>
Expand Down Expand Up @@ -163,7 +181,12 @@ function App() {
{t("Select game category")} :
</div>
<div>
<select className="FormControl Select CategorySelect" name="categoryID" onChange={handleCategoryChange}>
<select
className="FormControl Select CategorySelect"
name="categoryID"
onChange={handleCategoryChange}
value={categoryID}
>
<option value={-1}>----------</option>
{categoryOptions.map(({ label, value }) => (
<option key={label} value={value}>
Expand All @@ -176,8 +199,7 @@ function App() {
</div>
<div className="FormItem games-list">
<label className="label" htmlFor="rootDir">
{t("Games")}{" "}
{games.length ? `(${games.length}` + (newGames.length ? ` + ${newGames.length} ${t("unsaved")})` : ")") : ""}:
{t("Games")} {totalGamesLabel}:
</label>
<div className="list-actions">
<button className="FormControl btn btn-sm" onClick={refreshGameList} disabled={!rootDir || categoryID === -1}>
Expand All @@ -191,15 +213,7 @@ function App() {
+ {t("Add")}
</button>
</div>
<div className="ListBox">
<ul role="listbox">
{allgames.map((g) => (
<li key={`${g.filename}${g.srcPath}${g.id}`} className={!g.hsk ? "unsaved" : ""}>
{g.name}
</li>
))}
</ul>
</div>
<GameList games={games} onToggleDelete={handleGameToggleDelete} />
<span className="FormError">{errors.rootDir}</span>
</div>
<Alert type={message?.type} message={message?.content} />
Expand Down
38 changes: 2 additions & 36 deletions frontend/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,41 +86,6 @@
}
}

.ListBox {
position: relative;
border: 0.1rem solid var(--color-border-secondary);
border-radius: 0.5em;
> ul {
margin: 0;
overflow: auto;
height: 10rem;
> li {
list-style: none;
padding: 0 1rem;
height: 2rem;
line-height: 2rem;

&.unsaved {
font-weight: 700;
color: var(--color-gh-blue);
position: relative;
&::before {
content: "* ";
position: absolute;
left: 0;
padding: 0.2rem;
}
}
}
}

button {
position: absolute;
bottom: 0.5rem;
right: 0.5rem;
}
}

.SubmitButtonWrapper {
text-align: center;
}
Expand Down Expand Up @@ -162,12 +127,13 @@
transition-duration: 0.1s;
}
.btn-lg {
height: 2.6rem;
height: 2.4rem;
font-size: 1rem;
}

.btn-sm {
height: 1.5rem;
min-width: 1.5rem;
font-size: 0.7rem;
line-height: 0.7rem;
border-radius: 0.4em;
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/Emoji.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from "react";

function Emoji({ children, ariaLabel }) {
return (
<span className="emoji" role="img" aria-label={ariaLabel}>
{children}
</span>
);
}

export default Emoji;
30 changes: 30 additions & 0 deletions frontend/src/GameList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import Emoji from "./Emoji";
import "./GameList.scss";

const getClassName = (g) => {
let className = "";
if (!g.hsk) className += "unsaved ";
if (g.deleted) className += "mark-deleted";
return className;
};

function GameList({ games, onToggleDelete }) {
return (
<div className="ListBox">
<ul role="listbox">
{games.map((g, i) => (
<li key={`${g.filename}${g.srcPath}${g.id}`} className={getClassName(g)}>
{g.name}
<button className="delete-btn btn btn-sm" onClick={onToggleDelete(i)}>
<span className="emoji" role="img" aria-label="delete icon"></span>
<Emoji ariaLabel="delete icon">{g.deleted ? "✅" : "❌"}</Emoji>
</button>
</li>
))}
</ul>
</div>
);
}

export default GameList;
52 changes: 52 additions & 0 deletions frontend/src/GameList.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import "variables.scss";

.ListBox {
position: relative;
border: 0.1rem solid var(--color-border-secondary);
border-radius: 0.5em;
> ul {
margin: 0;
overflow: auto;
height: 14.4rem;
> li {
list-style: none;
padding: 0 1rem;
height: 2.4rem;
line-height: 2.4rem;
position: relative;
z-index: 10000;

&.unsaved {
font-weight: 700;
color: var(--color-gh-blue);
position: relative;
&::before {
content: "* ";
position: absolute;
left: 0;
padding: 0.2rem;
}
}

&.mark-deleted {
text-decoration: line-through;
color: var(--color-text-disabled);
}

> .delete-btn {
visibility: hidden;
position: absolute;
right: 2em;
top: 0.5em;
}

&:hover {
background-color: var(--color-gh-blue);
color: white;
> .delete-btn {
visibility: visible;
}
}
}
}
}
4 changes: 4 additions & 0 deletions frontend/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,7 @@ button:disabled {
cursor: not-allowed;
pointer-events: none;
}

.emoji {
font-family: -apple-system, "Segoe UI emoji";
}
2 changes: 1 addition & 1 deletion frontend/src/translation/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"Save Changes": "Save Changes",
"directory": "directory",
"not exists": "not exists",
"game(s) added successfully!": "game(s) added successfully!",
"Changes saved successfully!": "Changes saved successfully!",
"failed": "failed",
"Action Game": "Action Game",
"Shoot Game": "Shoot Game",
Expand Down
Loading

0 comments on commit 12c9f4f

Please sign in to comment.