mirror of
https://github.com/bakustarver/rpgmakermlinux-cicpoffs.git
synced 2025-04-22 06:02:04 +02:00
136 lines
4.5 KiB
Ruby
136 lines
4.5 KiB
Ruby
# ======================================================================
|
|
# MKXP-Z Custom tilemap workaround tools
|
|
#
|
|
# Authors: Roza, Taeyeon Mori
|
|
#
|
|
# Contains library code only, must be added to custom
|
|
# tilemap classes using a preload patch or similar.
|
|
# ======================================================================
|
|
# SUPER TILEMAP VERTICAL WRAPPER THING
|
|
#
|
|
# This is a little fix for Pokemon Essentials' custom tilemap code
|
|
# that works around MKXP's GPU texture size limit that would normally
|
|
# stop you from playing a lot of games.
|
|
#
|
|
# The concept is simple enough: If your tileset is too big, a new
|
|
# bitmap will be constructed with all the excess pixels sent to the
|
|
# image's right side. This basically means that you now have a limit
|
|
# far higher than you should ever actually need.
|
|
#
|
|
# 1024 -> 4096
|
|
# 2048 -> 16384 (enough to get the normal limit)
|
|
# 4096 -> 65536 (enough to load pretty much any tileset)
|
|
# 8192 -> 262144
|
|
# 16384 -> 1048576 (what most people have at this point)
|
|
#
|
|
# Because of the extra math the game will have to do to find the right
|
|
# pixels, this will probably cause a slight performance hit while on these
|
|
# maps which would normally be megasurfaces.
|
|
#
|
|
# This script was written for games based on 17.1. This workaround is
|
|
# already implemented in 19.
|
|
#
|
|
# ~Roza/Zoroark
|
|
#=======================================================================
|
|
|
|
module TileWrap
|
|
|
|
MAX_TEX_SIZE = Bitmap.max_size
|
|
TILESET_WIDTH = 0x100
|
|
MAX_TEX_SIZE_BOOSTED = MAX_TEX_SIZE**2/TILESET_WIDTH
|
|
|
|
def self.clamp(val, min, max)
|
|
val = max if val > max
|
|
val = min if val < min
|
|
return val
|
|
end
|
|
|
|
def self.wrapTileset(originalbmp)
|
|
width = originalbmp.width
|
|
height = originalbmp.height
|
|
if width == TILESET_WIDTH && originalbmp.mega?
|
|
columns = (height / MAX_TEX_SIZE.to_f).ceil
|
|
|
|
if columns * TILESET_WIDTH > MAX_TEX_SIZE
|
|
raise "Tilemap is too long!\n\nSIZE: #{originalbmp.height}px\nHARDWARE LIMIT: #{MAX_TEX_SIZE}px\nBOOSTED LIMIT: #{MAX_TEX_SIZE_BOOSTED}px"
|
|
end
|
|
bmp = Bitmap.new(TILESET_WIDTH*columns, MAX_TEX_SIZE)
|
|
remainder = height % MAX_TEX_SIZE
|
|
|
|
columns.times{|col|
|
|
srcrect = Rect.new(0, col * MAX_TEX_SIZE, width, (col + 1 == columns) ? remainder : MAX_TEX_SIZE)
|
|
bmp.blt(col*TILESET_WIDTH, 0, originalbmp, srcrect)
|
|
}
|
|
return bmp
|
|
end
|
|
|
|
return originalbmp
|
|
end
|
|
|
|
def self.wrapRect(srcrect)
|
|
column, y = srcrect.y.divmod MAX_TEX_SIZE
|
|
raise "Rect split across column wrap!" if y + srcrect.height > MAX_TEX_SIZE
|
|
return srcrect if column == 0
|
|
Rect.new(column * MAX_TEX_SIZE + srcrect.x, y, srcrect.width, srcrect.height)
|
|
end
|
|
|
|
def self.wrapRect!(rect)
|
|
column, y = rect.y.divmod MAX_TEX_SIZE
|
|
raise "Rect split across column wrap!" if y + rect.height > MAX_TEX_SIZE
|
|
return if column == 0
|
|
rect.x = column * MAX_TEX_SIZE + rect.x
|
|
rect.y = y
|
|
end
|
|
|
|
def self.blitWrappedPixels(destX, destY, dest, src, srcrect)
|
|
if (srcrect.y + srcrect.width < MAX_TEX_SIZE)
|
|
# Save the processing power
|
|
return dest.blt(destX, destY, src, srcrect)
|
|
end
|
|
merge = (srcrect.y % MAX_TEX_SIZE) > ((srcrect.y + srcrect.height) % MAX_TEX_SIZE)
|
|
|
|
srcrect.x = clamp(srcrect.x, 0,TILESET_WIDTH)
|
|
srcrect.width = clamp(srcrect.width, 0, TILESET_WIDTH - srcrect.x)
|
|
col = (srcrect.y / MAX_TEX_SIZE.to_f).floor
|
|
srcX = col * TILESET_WIDTH + srcrect.x
|
|
srcY = srcrect.y % MAX_TEX_SIZE
|
|
|
|
if !merge
|
|
dest.blt(destX, destY, src, Rect.new(srcX, srcY, srcrect.width, srcrect.height))
|
|
else
|
|
#FIXME won't work on heights longer than two columns, but nobody should need
|
|
# more than 32k pixels high at once anyway
|
|
side = {:a => MAX_TEX_SIZE - srcY, :b => srcrect.height - (MAX_TEX_SIZE - srcY)}
|
|
dest.blt(destX, destY, src, Rect.new(srcX, srcY, srcrect.width, side[:a]))
|
|
dest.blt(destX, destY + side[:a], src, Rect.new(srcX + TILESET_WIDTH, 0, srcrect.width, side[:b]))
|
|
end
|
|
end
|
|
|
|
# May be applied using Module#prepend
|
|
# it's probably better to integrate custom tilemap code manually
|
|
# XXX: is it OK to dispose of the original bitmaps?
|
|
module TilemapPatch
|
|
def tileset=(value)
|
|
if value.mega?
|
|
super TileWrap::wrapTileset value
|
|
value.dispose
|
|
else
|
|
super value
|
|
end
|
|
end
|
|
end
|
|
|
|
module SpritePatch
|
|
def bitmap=(bmp)
|
|
if bmp.mega?
|
|
super TileWrap.wrapTileset bmp
|
|
bmp.dispose
|
|
else
|
|
super bmp
|
|
end
|
|
end
|
|
def src_rect=(rect)
|
|
super TileWrap.wrapRect rect
|
|
end
|
|
end
|
|
end
|