Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automate the tilemap size fetch #105

Merged
merged 2 commits into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,6 @@ Fill this file following the below instructions:
4. Leave the vision and enter into it again, and then re-run how much times minus 1 you needed to see changes on `020039CC` (for example, 4 - 1 = 3 times), and get the value at **r0** (for example, on vision 5 is `081B8A28`)
5. You should put this values on `tilemap` without the first 2 digits. For instance: `tilemap: 0x1B8A28`

##### Size

1. Within a vision, add a breakpoint on `0800FF7E` and run the game
2. Go to the address pointed by **r0** and change this byte to `00`. It will be our tile A
3. In the game, you should move Klonoa away from this byte and then return. You'll see that our tile A now is empty
4. Now we should get the tile B (that is bellow A). Set again the breakpoint, and remove how much tiles bellow Klonoa to drop him 1 level
5. Find the tile B looking around him
6. Subtract the address of tile A and tile B. The result is the vision width (on vision 5 is `270`)
7. Now divide the width with the length of the tilemap (you can get it running this application locally and oppeing the vision). The result is the height (on vision 5 is `120`)

##### Objects

1. Go to the previous vision file, and get the address which start the OAM, for example, at the vision 1-3 is `E4DF0`
Expand Down
12 changes: 8 additions & 4 deletions brush/src/components/Map/TilemapLayer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ class TilemapLayer extends React.Component {
vision: {
infos: {
tilemap: {
height,
scheme,
width,
},
},
tilemap,
tilemapSize: {
height,
width,
},
},
} = this.props

Expand Down Expand Up @@ -74,15 +76,17 @@ TilemapLayer.propTypes = {
vision: PropTypes.shape({
infos: PropTypes.shape({
tilemap: PropTypes.shape({
height: PropTypes.number.isRequired,
scheme: PropTypes.arrayOf(PropTypes.shape({
ids: PropTypes.arrayOf(PropTypes.number).isRequired,
name: PropTypes.string.isRequired,
})),
width: PropTypes.number.isRequired,
}).isRequired,
}).isRequired,
tilemap: PropTypes.object.isRequired,
tilemapSize: PropTypes.shape({
height: PropTypes.number.isRequired,
width: PropTypes.number.isRequired,
}).isRequired,
}).isRequired,
}

Expand Down
6 changes: 4 additions & 2 deletions brush/src/components/Map/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ const Map = ({
const {
infos: {
tilemap: {
height,
scheme,
totalStages,
width,
},
},
tilemapSize: {
height,
width,
},
} = vision

const [selectedPointInfos, setSelectedPointInfos] = useState(null)
Expand Down
7 changes: 4 additions & 3 deletions brush/src/providers/VisionProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ const VisionProvider = ({ children }) => {
const forceUpdate = useForceUpdate()

const emptyState = {
infos: { index: 0, tilemap: { height: 0, scheme: [], width: 0 }, world: 0 },
infos: { index: 0, tilemap: { scheme: [] }, world: 0 },
objects: [],
objectsDiffMap: {},
state: 'noSelected',
tilemap: new Uint8Array(),
tilemapSize: { height: 0, width: 0 },
}

const [vision, setVision] = useState(emptyState)
Expand All @@ -44,11 +45,11 @@ const VisionProvider = ({ children }) => {
})

const updateTilemapPoint = (x, y, newTileId) => {
vision.tilemap[x + (y * vision.infos.tilemap.width)] = newTileId
vision.tilemap[x + (y * vision.tilemapSize.width)] = newTileId
}

const getTilemapPoint = (x, y) =>
vision.tilemap[x + (y * vision.infos.tilemap.width)]
vision.tilemap[x + (y * vision.tilemapSize.width)]

const updateObjectsDiffMap = (index, key, value) => {
if (key === 'kind') {
Expand Down
30 changes: 25 additions & 5 deletions scissors/src/visionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,40 @@ const extractPortals = (romBuffer, [addressStart, addressEnd]) =>
|> filter(({ data }) =>
data.kind !== null)

const getVisionSize = (romBuffer, world, vision) => {
const bytesPerVision = 6
const totalVisionsPerWorld = 9
const worldsOffset = (world - 1) * totalVisionsPerWorld * bytesPerVision
const visionsOffset = (vision - 1) * bytesPerVision

const { height, width } = binary.parse(romBuffer)
.skip(0x51C80)
.skip(worldsOffset + visionsOffset)
.word16lu('width')
.skip(0x142)
.word16lu('height')
.vars

return { height, width }
}

const getVision = (romBuffer, world, vision) => {
const infos = loadVisionInfo(world, vision)
const addressStart = visionHasCustomTilemap(romBuffer, infos) ?
infos.rom.customTilemap :
infos.rom.tilemap

// The first 3 bytes of tilemap isn't the tiles,
// but something unknown important to plot the level at the game.
// So this proxy is useful to abstract Brush about this detail
// The first 4 bytes of the tilemap isn't the tiles itself,
// but a metadata important to uncompress the data.
// So this proxy is useful to abstract to Brush this detail.
const fullTilemap = extractFullTilemap(romBuffer, addressStart)

const tilemapProxy = new Proxy(fullTilemap, {
get: (target, property) => {
if (isNumeric(property)) {
const numericProp = Number(property)

return target[numericProp + 3]
return target[numericProp + 4]
}

if (property === 'length') {
Expand All @@ -103,7 +120,7 @@ const getVision = (romBuffer, world, vision) => {

if (isNumeric(property)) {
const numericProp = Number(property)
self[numericProp + 3] = value
self[numericProp + 4] = value

return self
}
Expand All @@ -117,6 +134,8 @@ const getVision = (romBuffer, world, vision) => {
const objects = extractObjects(romBuffer, infos.rom.objects)
const portals = extractPortals(romBuffer, infos.rom.portals)

const tilemapSize = getVisionSize(romBuffer, Number(world), Number(vision))

const objectsKindToSprite =
objects.map(({ data: { kind, sprite } }) => [kind, sprite])
|> fromPairs
Expand All @@ -127,6 +146,7 @@ const getVision = (romBuffer, world, vision) => {
objectsKindToSprite,
portals,
tilemap: tilemapProxy,
tilemapSize,
}
}

Expand Down
2 changes: 0 additions & 2 deletions scissors/src/visions/infos/1-1.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export default {
},
tilemap: {
totalStages: 3,
height: 60,
width: 420,
scheme: [
{
name: 'grass',
Expand Down
2 changes: 0 additions & 2 deletions scissors/src/visions/infos/1-2.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export default {
},
tilemap: {
totalStages: 3,
height: 60,
width: 300,
scheme: [
{
name: 'grass',
Expand Down
2 changes: 0 additions & 2 deletions scissors/src/visions/infos/1-3.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export default {
},
tilemap: {
totalStages: 5,
height: 59,
width: 300,
scheme: [
{
name: 'rock',
Expand Down
2 changes: 0 additions & 2 deletions scissors/src/visions/infos/1-5.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export default {
},
tilemap: {
totalStages: 4,
height: 120,
width: 270,
scheme: [
{
name: 'rope',
Expand Down
2 changes: 0 additions & 2 deletions scissors/src/visions/infos/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export default {
},
tilemap: {
totalStages: 0, // TODO
height: 0, // TODO
width: 0, // TODO
scheme: [
{
name: '', // TODO
Expand Down