mirror of
https://github.com/cave-story-randomizer/cave-story-randomizer
synced 2024-11-08 16:04:30 +00:00
Refactored to use TscFile class and read from dropped directory.
This commit is contained in:
parent
0094c34e51
commit
ea1d0720fc
276
docs/item locations.txt
Normal file
276
docs/item locations.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
---------------------------
|
||||
- 3-02 Upgrade Locations -
|
||||
---------------------------
|
||||
|
||||
** LIFE CAPSULES **
|
||||
These will give a set Max HP boost, between 3 and 5, depending on the capsule.
|
||||
You will have 50 life if you find them all, 55 if you include the bonus
|
||||
capsule. Some of these are possible to miss.
|
||||
|
||||
- First Cave: In plain sight as you descend toward the Polar Star, on the left
|
||||
wall. +3 HP.
|
||||
|
||||
- Mimiga Village: Found in Yamanshita Farm on the top of Mimiga Village. Head
|
||||
to the far right, it's in the small pool. +3 HP.
|
||||
|
||||
- Egg Corridor: At the very beginning, you have to drop down to the left just
|
||||
as the Basil spark hits the wall then chase it so it extends its loop length.
|
||||
+3 HP.
|
||||
|
||||
- Egg Corridor: Go through Cthulhu's Abode and out the top door. Jump left.
|
||||
+4 HP.
|
||||
|
||||
- Bushlands: Just past where you found Santa's Key, go east to a set of two
|
||||
horizontal rows of star blocks, jump on them and to the left. +5 HP.
|
||||
|
||||
- Bushlands: In the Execution Chamber, the tall building with the skull on it
|
||||
to the right of Kazuma's shack. +5 HP.
|
||||
|
||||
- Sand Zone: East of Curly's House and past the Sun Stones, it's in the top of
|
||||
the first thick pillar made up of star blocks. Try not to blow up all the star
|
||||
blocks when fighting the Polishes to create a path and reach it. +5 HP.
|
||||
|
||||
- Sand Zone: At the end of the hidden path behind a pawpad block on the far
|
||||
right wall between the Sun Stones and Jenka's house, behind a line of star
|
||||
blocks. Found next to a chest containing one of Jenka's dogs. +5 HP.
|
||||
|
||||
- Labyrinth: Nestled next to the left wall of the first room of the labyrinth
|
||||
when you're sent there, a ways up into the room. +5 HP.
|
||||
|
||||
- Plantation: Sitting on a platform hanging from the far upper-left ceiling.
|
||||
+4 HP.
|
||||
|
||||
- Plantation: Talk to the puppy that appears on the left platform just under
|
||||
the red skull signs on the top right section of the Plantation after Momorin's
|
||||
finished the rocket. +5 HP.
|
||||
|
||||
- Sanctuary: Bonus life capsule. Found in plain sight as you make your
|
||||
initial descent. +5 HP.
|
||||
|
||||
|
||||
** MISSILE EXPANSIONS **
|
||||
These each give +5 Max Missile Launcher Ammo. Your max ammo carries over to
|
||||
the Super Missile Launcher. You'll have 30 missile ammo if you find them all,
|
||||
54(!!) with the bonus.
|
||||
|
||||
- Bushlands: To the left of the hut in the air above the shack where Kazuma's
|
||||
trapped. Jump around the series of platforms around where the Save Point is
|
||||
between the Power Supply Room and Kazuma's shack to reach it.
|
||||
|
||||
- Bushlands: Inside the very hut that the previous expansion's sitting next
|
||||
to. Opening it will trigger a fight with Kulala.
|
||||
|
||||
- Egg Corridor?: When you go back to the Egg Corridor later in the game,
|
||||
you'll find the eggs have hatched. The dragon where Egg 12 used to be is quite
|
||||
pissed and will fervently guard the chest containing this expansion.
|
||||
|
||||
- Egg Corridor?: In the ruins of the Egg observation Room, in plain sight.
|
||||
Opening it will trigger a fight with The Sisters.
|
||||
|
||||
- Sanctuary: Bonus expansion. Just before you fight the Heavy Press at the
|
||||
far west end of Blood-Stained Sanctuary B3, just past the pillar with 3 Deletes
|
||||
covering it, in the room filled with flying Butes and with a hanging platform
|
||||
with an arrow Bute on either side. Above this platform is a single Star Block
|
||||
concealing a chest containing this massive expansion of 24 Misisles.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
** KEY ITEMS **
|
||||
|
||||
- Map System
|
||||
Allows you to press the - Button on the Wii Remote to bring up a map of the
|
||||
room you're in. The map is tiny, doesn't show your current position and has a
|
||||
strange graphical glitch that makes the rightmost section of mose large areas
|
||||
unviewable, so it's of very little use except collectibility.
|
||||
|
||||
- Silver Locket
|
||||
An item found in the fishing hole to the west of Mimiga Village. It triggers
|
||||
an event in the warehouse at the bottom right of the village.
|
||||
|
||||
- Arthur's Key
|
||||
Found at Arthur's grave in the Cemetary. Use it to access Arthur's house, at
|
||||
the bottom-left of Mimiga Village.
|
||||
|
||||
- ID Card
|
||||
Found in Egg #06 in the Egg Corridor. Use it in Egg #01 to open the barrier to
|
||||
the eastern edge of the Corridor.
|
||||
|
||||
- Santa's Key
|
||||
The key to Santa's house that he dropped to the east in the Bushlands.
|
||||
|
||||
- Rusty Key
|
||||
A key Kazuma found in the room he's stuck in. Gives access to the Power
|
||||
Control Room in the Bushlands.
|
||||
|
||||
- Gum Key
|
||||
Another key conviniently located in Kazuma's captivity room. It opens up the
|
||||
gum room in the very upper-right corner of the Bushlands.
|
||||
|
||||
- Jellyfish Juice
|
||||
A jar full of juice that you can find by defeating the huge jellyfish stuck in
|
||||
the ceiling a bit east of Santa's house that only appears after talking to
|
||||
Chako. Use it to put out fireplace fires; it's also one of three components
|
||||
needed to create a bomb. It's the only Key Item you can receive more than
|
||||
once, but you may only carry one at a time.
|
||||
|
||||
- Chako's Rouge
|
||||
Some red lipstick. Obtained by examining Chako's fireplace before you obtain
|
||||
Jellyfish Jelly, causing her to walk up to you and explain some things, and
|
||||
then sleeping in her bed while she's standing there. It has no use, other than
|
||||
proof that you really, really, REALLY like Mimigas, you scoundrel.
|
||||
|
||||
- Charcoal
|
||||
A lump of charcoal found by putting out the fireplace in Santa's house. It's
|
||||
one of three components needed to create a bomb.
|
||||
|
||||
- Gum Base
|
||||
A stick of chewing gum found in the room in the very top-right corner of the
|
||||
Bushlands. It's one of three components needed to create a bomb.
|
||||
|
||||
- Bomb
|
||||
A bomb crafted by Malco, in the Power Generator Room of the Bushlands. Use it
|
||||
to blow open the door of the building Kazuma's trapped inside.
|
||||
|
||||
- Curly's Panties
|
||||
Found in a hidden alcove behind the wall in the bedroom of Curly Brace's house
|
||||
in the Sand Zone. They have no use, other than proof that you really, really,
|
||||
REALLY like robots. If you own both this and Chako's Rouge, you are officially
|
||||
the most envied man in Cave Story! Okay, I made that up.
|
||||
|
||||
- Hajime
|
||||
A dog that stays in Curly Brace's bedroom in the Sand Zone. One of Jenka's
|
||||
five missing dogs. He's the leader of the bunch.. or so he claims.
|
||||
Arf!
|
||||
|
||||
- Mick
|
||||
One of Jenka's dogs. He's supposedly an adept treasure hunter, and loves to
|
||||
sleep in treasure chests. What he does with the contents is anyone's guess.
|
||||
Found in a chest at the end of a hidden path between the Sun Stones and Jenka's
|
||||
house.
|
||||
Woof woof!
|
||||
|
||||
- Shinobu
|
||||
Another of Jenka's dogs. He has poor vision so he prefers to stay in dark
|
||||
places. Found in an abandoned house at the end of a hidden road that begins in
|
||||
a false ceiling along the path to the Sand Zone warehouse.
|
||||
Bow wow wow!
|
||||
|
||||
- Kakeru
|
||||
Yet another dog of Jenka's. He loves bones and has buried them all over the
|
||||
place. You can find him at the end of the sand-bottomed section of the path
|
||||
toward the Sand Zone warehouse.
|
||||
Woof woof woof woof!
|
||||
|
||||
- Nene
|
||||
A beautiful dog, the only female of the group. She sleeps all the time, and
|
||||
can be found taking one of her long naps at the very end of the lower path of
|
||||
the Sand Zone, right next to the warehouse.
|
||||
Wan...
|
||||
|
||||
- Life Pot
|
||||
Restores all of your HP when used. It can only be used once, and there are
|
||||
only two in the entire game, so use wisely!
|
||||
|
||||
- Turbocharge
|
||||
If you chose to take the Machine Gun from Curly in the Sand Zone, then you can
|
||||
receive this for free from the Gaudi shopkeeper, Chaba, in the Labyrinth. It
|
||||
speeds up the recovery rate of ammo for the Machine Gun.
|
||||
|
||||
- Clinic Key
|
||||
Opens the door to the Labyrinth Clinic, the building with the cross above it
|
||||
up and west from the Camp. Obtained from Dr. Gero, the physician in the Camp.
|
||||
|
||||
- Arms Barrier
|
||||
Halves weapon EXP lost when you take damage. Found the top part of the Camp,
|
||||
accessible via a hidden passageway in the ceiling in the large Labyrinth room
|
||||
from which you can access the normal Camp entrance and the Clinic nearby.
|
||||
Unless you took the Machine Gun, you'll have to come back to this area with the
|
||||
Booster to be able to reach it.
|
||||
|
||||
- Cure-All
|
||||
A pill found in the abandoned Clinic in the Labyrinth. It supposedly has the
|
||||
ability to cure anything. Give it to the Physician in the Labyrinth Camp.
|
||||
|
||||
- Booster v0.8
|
||||
A jetpack that can be equipped and unequipped from the inventory menu. Once
|
||||
it's equipped, press and hold Jump while airborne to launch upward for a few
|
||||
moments. Can only be used once in the air until you hit the ground again.
|
||||
Received in the Labyrinth, past the Clinic and Camp.
|
||||
|
||||
- Booster v2.0
|
||||
A powerful jetpack that allows you to move freely for a time at high speeds in
|
||||
midair if you press the jump button. If you want this instead of the Booster
|
||||
v0.8, jump over the large gap in the Labyrinth room where Professor Booster
|
||||
falls down by leaping just at the red marker on the ground. It's required if
|
||||
you wish to access the hidden, super-difficult Sanctuary area at the end of the
|
||||
game, but you may want to go for the normal ending with Booster v0.8 first.
|
||||
|
||||
- Tow Rope
|
||||
A tow cable found in the far lower-right corner of The Core (only appears if
|
||||
you didn't take the Booster v0.8). It was used by the robots who came to the
|
||||
island years ago to carry downed comrades.
|
||||
|
||||
- Curly's Air Tank
|
||||
Given to you by Curly Brace after the events at the Core. With it, you're
|
||||
automatically encased in a bubble whenever you enter water, giving you infinite
|
||||
air.
|
||||
|
||||
- Alien Medal
|
||||
Reward for defeating Ironhead (the boss of the Waterway) without taking any
|
||||
damage. It's engraved with an image of Ikachan, the hero of a game named after
|
||||
himself that was Studio Pixel's previous work before Cave STory.
|
||||
|
||||
- Whimsical Star
|
||||
A trinket that you can receive from Chaba, the Gaudi shopkeep in the Labyrinth,
|
||||
if you talk to him with the Spur weapon in your posession. It will cause small
|
||||
stars to float around you as a meagre shield when you charge the Spur to MAX.
|
||||
|
||||
- Teleporter Room Key
|
||||
This key is visible but unobtainable behind a cluster of instant-death spikes
|
||||
in the pools at the bottom of the Plantation. You'll need to talk to Kanpachi,
|
||||
the fishing Mimiga, to help you get it. Use it to unlock the room just west of
|
||||
where it was fished up.
|
||||
|
||||
- Sue's Letter
|
||||
You'll find this stuffed in your inventory after you wake up inside the jail.
|
||||
It's a leeter from Sue explaining a lot of what's been going on as far as the
|
||||
story that you've had to just piece together by this point. It also contains
|
||||
the password to enter the Safe House on the Plantation.
|
||||
|
||||
- Mimiga Mask
|
||||
A head covering that looks just like a Mimiga. Wearing it will allow you to
|
||||
speak to the Mimiga in the Plantation who aren't allowed to speak with humans.
|
||||
|
||||
- Broken Sprinkler
|
||||
A broken water sprinkler from the Plantation. Useless by itself, but can be
|
||||
traded to Megane in the Plantation Rest Area.
|
||||
|
||||
- Sprinkler
|
||||
It's new... isn't it? This can be taken back to Momorin in the Plantation Safe
|
||||
House to help complete her rocket.
|
||||
|
||||
- Controller
|
||||
A technologically impressive device that could only have been made by a master
|
||||
technician. Too bad he's a big fat coward. Obtained from Itoh after giving
|
||||
Momorin the Sprinkler.
|
||||
|
||||
- Mushroom Badge
|
||||
Useless item given to you by Ma Pignon in hopes you'll leave him alone. I hope
|
||||
you know how to answer his questions correctly even if you want this garbage.
|
||||
|
||||
- Ma Pignon
|
||||
Mystical, ultra-rare mushroom that's said to restore people's memories. Has a
|
||||
smart-aleck personality and is known to be a surprisingly potent combatant, as
|
||||
well. Found in the small storage room above the Mimiga Cemetar.
|
||||
|
||||
- Mister Little
|
||||
This guy's very, very hard to see and has gotten himself very, very lost. At
|
||||
the end of the game, you can find him wandering around the Mimiga Cemetary.
|
||||
It's said he is the proud owner of the world's most splendid gun. Has a
|
||||
fascination with fine blades.
|
||||
|
||||
- Medal of the Red Ogre (aka Clay Figure Medal)
|
||||
Proof of the warrior who's finally able to put an end to the Red Ogre. It's
|
||||
extremely heavy despite its size.
|
71
src/lib/classic.lua
Normal file
71
src/lib/classic.lua
Normal file
|
@ -0,0 +1,71 @@
|
|||
-- Copyright (c) 2014, rxi
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in
|
||||
-- the Software without restriction, including without limitation the rights to
|
||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
-- of the Software, and to permit persons to whom the Software is furnished to do
|
||||
-- so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
|
||||
local Object = {}
|
||||
Object.__index = Object
|
||||
|
||||
function Object:new()
|
||||
end
|
||||
|
||||
function Object:extend()
|
||||
local cls = {}
|
||||
for k, v in pairs(self) do
|
||||
if k:find("__") == 1 then
|
||||
cls[k] = v
|
||||
end
|
||||
end
|
||||
cls.__index = cls
|
||||
cls.super = self
|
||||
setmetatable(cls, self)
|
||||
return cls
|
||||
end
|
||||
|
||||
function Object:implement(...)
|
||||
for _, cls in pairs({...}) do
|
||||
for k, v in pairs(cls) do
|
||||
if self[k] == nil and type(v) == "function" then
|
||||
self[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Object:is(T)
|
||||
local mt = getmetatable(self)
|
||||
while mt do
|
||||
if mt == T then
|
||||
return true
|
||||
end
|
||||
mt = getmetatable(mt)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Object:__tostring()
|
||||
return "Object"
|
||||
end
|
||||
|
||||
function Object:__call(...)
|
||||
local obj = setmetatable({}, self)
|
||||
obj:new(...)
|
||||
return obj
|
||||
end
|
||||
|
||||
return Object
|
198
src/main.lua
198
src/main.lua
|
@ -2,60 +2,23 @@ io.stdout:setvbuf("no")
|
|||
|
||||
require 'lib.strict'
|
||||
|
||||
local _ = require 'lib.moses'
|
||||
local Serpent = require 'lib.serpent'
|
||||
Class = require 'lib.classic'
|
||||
_ = require 'lib.moses'
|
||||
Serpent = require 'lib.serpent'
|
||||
|
||||
local lf = love.filesystem
|
||||
lf = love.filesystem
|
||||
|
||||
local MODE_READ_BINARY = 'rb'
|
||||
local MODE_WRITE_BINARY = 'wb'
|
||||
|
||||
function readLittleEndian(file, bytes)
|
||||
local string = file:read(2)
|
||||
local bytes = string:byte()
|
||||
-- print(string, type(bytes), bytes)
|
||||
return bytes
|
||||
end
|
||||
|
||||
-- https://gist.github.com/fdeitylink/3fded36e9187fe838eb18a412c712800
|
||||
-- -=~ PXM File Data ~=-
|
||||
-- maps must be minimum of 21x16
|
||||
function readPXM(filename)
|
||||
print('reading PXM: ' .. filename)
|
||||
local file = assert(io.open(filename, MODE_READ_BINARY))
|
||||
-- First three bytes are PXM, then 0x10.
|
||||
assert(file:read(3) == "PXM")
|
||||
assert(file:read(1):byte() == 0x10)
|
||||
|
||||
-- Then 0x_map_length - 2 bytes
|
||||
-- Then 0x_map_height - 2 bytes
|
||||
local length = readLittleEndian(file, 2)
|
||||
local height = readLittleEndian(file, 2)
|
||||
print('length:', length)
|
||||
print('height:', height)
|
||||
|
||||
-- Then 0x_map_tile_from_tileset for the rest of the file (numbered from 0, and going left to right, top to bottom) - 1 byte
|
||||
local tiles = {}
|
||||
for x = 1, length do
|
||||
tiles[x] = {}
|
||||
end
|
||||
for y = 1, height do
|
||||
for x = 1, length do
|
||||
tiles[x][y] = file:read(1):byte()
|
||||
end
|
||||
end
|
||||
-- Print result
|
||||
local XXX = 3
|
||||
for y = 1, height do
|
||||
local line = ""
|
||||
for x = 1, length do
|
||||
local tile = tiles[x][y]
|
||||
local len = string.len(tile)
|
||||
line = line .. string.rep(' ', XXX - len) .. tile
|
||||
end
|
||||
print(line)
|
||||
local LOG_LEVEL = 5
|
||||
local function _log(level, prefix, text, ...)
|
||||
if LOG_LEVEL >= level then
|
||||
print(prefix .. text, ...)
|
||||
end
|
||||
end
|
||||
function logError(...) _log(1, 'ERROR: ', ...) end
|
||||
function logWarning(...) _log(2, 'WARNING: ', ...) end
|
||||
function logNotice(...) _log(3, 'NOTICE: ', ...) end
|
||||
function logInfo(...) _log(4, 'INFO: ', ...) end
|
||||
function logDebug(...) _log(5, 'DEBUG: ', ...) end
|
||||
|
||||
local ITEM_DATA = {
|
||||
-- Weapons
|
||||
|
@ -77,123 +40,40 @@ local ITEM_DATA = {
|
|||
},
|
||||
}
|
||||
|
||||
function stringReplace(text, needle, replacement)
|
||||
local i = text:find(needle, 1, true)
|
||||
if i == nil then
|
||||
return text
|
||||
end
|
||||
local len = needle:len()
|
||||
local j = i + len - 1
|
||||
assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
|
||||
assert((j % 1 == 0), tostring(j))
|
||||
local a = text:sub(1, i - 1)
|
||||
local b = text:sub(j + 1)
|
||||
return a .. replacement .. b
|
||||
end
|
||||
local TSC_FILES = {
|
||||
'Pole.tsc',
|
||||
}
|
||||
|
||||
function readTSC(filename, decodedFilename)
|
||||
print('reading TSC: ' .. filename)
|
||||
local file = assert(io.open(filename, MODE_READ_BINARY))
|
||||
local filesize = file:seek("end")
|
||||
local encodingCharPosition = math.floor(filesize / 2)
|
||||
file:seek("set", encodingCharPosition)
|
||||
local encodingChar = file:read(1):byte()
|
||||
print(" filesize", filesize)
|
||||
print(" encoding char:", encodingChar)
|
||||
print(" encoding char position:", encodingCharPosition)
|
||||
|
||||
-- Decode
|
||||
local chars, len = {}, 0
|
||||
file:seek("set")
|
||||
for pos = 0, filesize - 1 do
|
||||
local byte = file:read(1):byte()
|
||||
if pos ~= encodingCharPosition then
|
||||
-- print(pos, encodingCharPosition)
|
||||
byte = (byte - encodingChar) % 256
|
||||
-- byte = byte - encodingChar
|
||||
end
|
||||
len = len + 1
|
||||
chars[len] = string.char(byte)
|
||||
end
|
||||
local decoded = table.concat(chars)
|
||||
|
||||
local t = {}
|
||||
decoded:gsub(".",function(c) table.insert(t,c) end)
|
||||
-- for i, c in ipairs(t) do
|
||||
local near = 10
|
||||
for i = 1270 - near, 1270 + near do
|
||||
local c = t[i]
|
||||
print (i, c, chars[i])
|
||||
-- print(string.byte(chars[i]) == string.byte(c), string.byte(chars[i]), string.byte(c))
|
||||
end
|
||||
|
||||
-- -- Replace
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.command, ITEM_DATA.iPanties.command)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.getText, ITEM_DATA.iPanties.getText)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.displayCmd, ITEM_DATA.iPanties.displayCmd)
|
||||
|
||||
-- Write
|
||||
-- return decoded
|
||||
local tmpFile, err = io.open(decodedFilename, MODE_WRITE_BINARY)
|
||||
assert(err == nil, err)
|
||||
tmpFile:write(decoded)
|
||||
tmpFile:flush()
|
||||
tmpFile:close()
|
||||
end
|
||||
|
||||
function writeTSC(filename)
|
||||
print('writing TSC: ' .. filename)
|
||||
local file = assert(io.open(filename, MODE_READ_BINARY))
|
||||
local filesize = file:seek("end")
|
||||
local encodingCharPosition = math.floor(filesize / 2)
|
||||
file:seek("set", encodingCharPosition)
|
||||
local encodingChar = file:read(1):byte()
|
||||
file:seek("set", encodingCharPosition)
|
||||
print(file:read(1))
|
||||
-- local encodingChar = 32
|
||||
print(" filesize", filesize)
|
||||
print(" encoding char:", encodingChar)
|
||||
print(" encoding char position:", encodingCharPosition)
|
||||
|
||||
-- Encode
|
||||
local chars, len = {}, 0
|
||||
file:seek("set")
|
||||
for pos = 0, filesize - 1 do
|
||||
local byte = file:read(1):byte()
|
||||
if pos ~= encodingCharPosition then
|
||||
byte = (byte + encodingChar) % 255
|
||||
end
|
||||
len = len + 1
|
||||
chars[len] = string.char(byte)
|
||||
end
|
||||
local decoded = table.concat(chars)
|
||||
|
||||
-- Write
|
||||
local tmpFile, err = io.open('TestingEncoded.tsc', MODE_WRITE_BINARY)
|
||||
assert(err == nil, err)
|
||||
tmpFile:write(decoded)
|
||||
tmpFile:flush()
|
||||
tmpFile:close()
|
||||
end
|
||||
|
||||
function love.load()
|
||||
-- readPXM('Pole.pxm')
|
||||
-- readTSC('Pole.tsc', 'Testing.tsc')
|
||||
-- writeTSC('Testing.tsc')
|
||||
-- readTSC('TestingEncoded.tsc', 'TestingDecoded.tsc')
|
||||
end
|
||||
-- function love.load()
|
||||
-- -- readPXM('Pole.pxm')
|
||||
-- -- readTSC('Pole.tsc', 'Testing.tsc')
|
||||
-- -- writeTSC('Testing.tsc')
|
||||
-- -- readTSC('TestingEncoded.tsc', 'TestingDecoded.tsc')
|
||||
-- end
|
||||
|
||||
function love.directorydropped(path)
|
||||
local success = lf.mount(path, 'data')
|
||||
assert(success)
|
||||
|
||||
-- Mount
|
||||
assert(lf.mount(path, 'data'))
|
||||
local items = lf.getDirectoryItems('/data')
|
||||
local containsStage = _.contains(items, 'Stage')
|
||||
assert(containsStage)
|
||||
local dirStage = '/data/Stage'
|
||||
|
||||
-- local items = lf.getDirectoryItems(dirStage)
|
||||
-- print(Serpent.block(items))
|
||||
local tscFiles = {}
|
||||
for _, filename in ipairs(TSC_FILES) do
|
||||
local path = dirStage .. '/' .. filename
|
||||
local TscFile = require 'tsc_file'
|
||||
tscFiles[filename] = TscFile(path)
|
||||
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.command, ITEM_DATA.iPanties.command)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.getText, ITEM_DATA.iPanties.getText)
|
||||
-- decoded = stringReplace(decoded, ITEM_DATA.wPolar.displayCmd, ITEM_DATA.iPanties.displayCmd)
|
||||
end
|
||||
|
||||
tscFiles['Pole.tsc']:writeTo('Testing.tsc')
|
||||
|
||||
-- Unmount
|
||||
assert(lf.unmount(path))
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
|
|
46
src/pxm_file.lua
Normal file
46
src/pxm_file.lua
Normal file
|
@ -0,0 +1,46 @@
|
|||
local function readLittleEndian(file, bytes)
|
||||
local string = file:read(2)
|
||||
local bytes = string:byte()
|
||||
-- print(string, type(bytes), bytes)
|
||||
return bytes
|
||||
end
|
||||
|
||||
-- https://gist.github.com/fdeitylink/3fded36e9187fe838eb18a412c712800
|
||||
-- -=~ PXM File Data ~=-
|
||||
-- maps must be minimum of 21x16
|
||||
local function readPXM(filename)
|
||||
print('reading PXM: ' .. filename)
|
||||
local file = assert(io.open(filename, MODE_READ_BINARY))
|
||||
-- First three bytes are PXM, then 0x10.
|
||||
assert(file:read(3) == "PXM")
|
||||
assert(file:read(1):byte() == 0x10)
|
||||
|
||||
-- Then 0x_map_length - 2 bytes
|
||||
-- Then 0x_map_height - 2 bytes
|
||||
local length = readLittleEndian(file, 2)
|
||||
local height = readLittleEndian(file, 2)
|
||||
print('length:', length)
|
||||
print('height:', height)
|
||||
|
||||
-- Then 0x_map_tile_from_tileset for the rest of the file (numbered from 0, and going left to right, top to bottom) - 1 byte
|
||||
local tiles = {}
|
||||
for x = 1, length do
|
||||
tiles[x] = {}
|
||||
end
|
||||
for y = 1, height do
|
||||
for x = 1, length do
|
||||
tiles[x][y] = file:read(1):byte()
|
||||
end
|
||||
end
|
||||
-- Print result
|
||||
local XXX = 3
|
||||
for y = 1, height do
|
||||
local line = ""
|
||||
for x = 1, length do
|
||||
local tile = tiles[x][y]
|
||||
local len = string.len(tile)
|
||||
line = line .. string.rep(' ', XXX - len) .. tile
|
||||
end
|
||||
print(line)
|
||||
end
|
||||
end
|
83
src/tsc_file.lua
Normal file
83
src/tsc_file.lua
Normal file
|
@ -0,0 +1,83 @@
|
|||
local C = Class:extend()
|
||||
|
||||
-- local MODE_READ_BINARY = 'rb'
|
||||
local MODE_WRITE_BINARY = 'wb'
|
||||
|
||||
function C:new(path)
|
||||
logInfo('reading TSC: ' .. path)
|
||||
|
||||
local file = lf.newFile(path)
|
||||
assert(file:open('r'))
|
||||
|
||||
local contents, size = file:read()
|
||||
self._text = self:_codec(contents, 'decode')
|
||||
|
||||
assert(file:close())
|
||||
assert(file:release())
|
||||
end
|
||||
|
||||
function C:writeTo(path)
|
||||
local encoded = self:_codec(self._text, 'encode')
|
||||
|
||||
local tmpFile, err = io.open(path, MODE_WRITE_BINARY)
|
||||
assert(err == nil, err)
|
||||
tmpFile:write(encoded)
|
||||
tmpFile:flush()
|
||||
tmpFile:close()
|
||||
end
|
||||
|
||||
function C:_codec(text, mode)
|
||||
-- Create array of chars.
|
||||
local chars = {}
|
||||
text:gsub(".", function(c) table.insert(chars, c) end)
|
||||
|
||||
-- Determine encoding char value
|
||||
local encodingCharPosition = math.floor(#chars / 2) + 1
|
||||
local encodingChar = chars[encodingCharPosition]:byte()
|
||||
if mode == 'decode' then
|
||||
encodingChar = encodingChar * -1
|
||||
elseif mode == 'encode' then
|
||||
-- OK!
|
||||
else
|
||||
error('Unknown codec mode: ' .. tostring(mode))
|
||||
end
|
||||
|
||||
logDebug(" filesize", #chars)
|
||||
logDebug(" encoding char:", encodingChar)
|
||||
logDebug(" encoding char position:", encodingCharPosition)
|
||||
|
||||
-- Encode or decode.
|
||||
for pos, char in ipairs(chars) do
|
||||
if pos ~= encodingCharPosition then
|
||||
local byte = (char:byte() + encodingChar) % 256
|
||||
chars[pos] = string.char(byte)
|
||||
end
|
||||
end
|
||||
local decoded = table.concat(chars)
|
||||
|
||||
-- local t = {}
|
||||
-- decoded:gsub(".",function(c) table.insert(t,c) end)
|
||||
-- local near = 7
|
||||
-- for i = encodingCharPosition - near, encodingCharPosition + near do
|
||||
-- local c = t[i]
|
||||
-- logDebug(i, c, c:byte())
|
||||
-- end
|
||||
|
||||
return decoded
|
||||
end
|
||||
|
||||
local function stringReplace(text, needle, replacement)
|
||||
local i = text:find(needle, 1, true)
|
||||
if i == nil then
|
||||
return text
|
||||
end
|
||||
local len = needle:len()
|
||||
local j = i + len - 1
|
||||
assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
|
||||
assert((j % 1 == 0), tostring(j))
|
||||
local a = text:sub(1, i - 1)
|
||||
local b = text:sub(j + 1)
|
||||
return a .. replacement .. b
|
||||
end
|
||||
|
||||
return C
|
Loading…
Reference in a new issue