User File #637896725554010464

Upload All User Files

#637896725554010464 - orb atlas lua

orbdrawlevel.lua
138 downloads
Uploaded 6/1/2022 9:29 AM by Mizumaririn (see all 1)
this is still work in progress. this revision is not exactly but similar to the one used for my encode.
to use it for smb3, you have to change the rom addresses
--save 128 frames of map palette, 	
local Image = {}
local ImageOld = {}
local first = 0
local black = 15
local ImageWidth = 2048
local ImageHeight = 1080
local OffsetLevelX = 0
local OffsetLevelY = 0
local StatusBarY = 432-9
local V1xDrawOffsetX = 256
local V2xDrawOffsetX = 512
local VStatusBarX = 1024
local VStatusBarY = 696
local VStatusBarY2 = 888
local VStatusBarSplit = 168
local drawFullLevel = false

function irq()
	local irqTime = os.clock()
	local loadBGPTTime = os.clock()
	loadBGPT()
	print("loadBGPT:", os.clock()-loadBGPTTime)
	local loadBGPalTime = os.clock()
	loadBGPal()
	print("loadBGPal:", os.clock()-loadBGPalTime)
	local cropLevelTime = os.clock()
	cropLevel()
	print("cropLevel:", os.clock()-cropLevelTime)
	local copyLevelTime = os.clock()
	copyLevel()
	print("copyLevel:", os.clock()-copyLevelTime)
	print("irq:", os.clock()-irqTime)
	
end
function init()
	os.execute("mkdir map")
	loadImagePal()
	preWriteHeader()
	for i=0,1080-1,1 do
		Image[i] = {}
		ImageOld[i] = {}
	end
	print("init completed")
end
function after()
	if first > 1 then
		exportImage()
	end
	first = first+1
	print(emu.framecount()," ok")
end

local TileLayout_ByTileset = 0x3d126	--indexed by Tileset<<1
local TileLayoutPage_ByTileset = 0x3d1d6	--the bank
local Tileset = 0x70a
--TileLayout	+0		+0x200
--				+0x100	+0x300
--	=Metatile
--16+TileLayoutPage_ByTileset*0x2000+TileLayout_ByTileset%0x2000

local PPU_BG_PAL = 0x3f00
local PPU_SPR_PAL = 0x3f10
--TileID & %11000000 => Palette

local Map_Tile_Layouts = 0x1859c
local World_Num = 0x729

local Level_7Vertical = 0x3ef
local Level_Width = 0x22

local Horz_Scroll_Hi = 0x12
local Vert_Scroll_Hi = 0x13
local Horz_Scroll = 0xfd
local Vert_Scroll = 0xfc

local Player_SpriteX = 0xab

local Raster_Effect = 0x101

local ImageRowSize = 0
local ImageSize = 0
local PalColours = 64
local PalSize = PalColours*4
local HeaderSize = 0x36
local FileTotalSize = 0
local OffsetImage = HeaderSize+PalSize

function preWriteHeader()
	ImageRowSize = math.ceil(ImageWidth/4)*4
	ImageSize = ImageRowSize * ImageHeight
	FileTotalSize = ImageSize+HeaderSize+PalSize
	OffsetImage = HeaderSize+PalSize
end

local scrollOld = {}
local scroll = {}

function dword(x)
	local t = {}
	for i=0,4-1,1 do
		t[i] = bit.band(x,255)
		x = bit.rshift(x,8)
	end
	return string.char(t[0],t[1],t[2],t[3])
end

function table.clone(org)
  return {table.unpack(org)}
end

local Header = ""
function writeHeader()
Header = "BM"..dword(FileTotalSize)..string.char(0,0,0,0)..dword(OffsetImage)..string.char(40,0,0,0)..dword(ImageWidth)..dword(ImageHeight)..string.char(1,0,8,0,0,0,0,0)..dword(ImageSize)..string.char(0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0)
end

local Pal = ""
function loadImagePal()
io.input("FCEUX.pal")
for i=0,64-1,1 do
	j = io.read(3)
	Pal = Pal..j.sub(j,3,3)..j.sub(j,2,2)..j.sub(j,1,1)..string.char(255)
end
end

local PatternTable = {}
function loadBGPT()
for i=0,256-1,1 do	--8 bytes
	local Metatile = {}
	for h=0,8-1,1 do	--bytes
		Metatile[h] = {}
		local Byt = ppu.readbyte(h+i*16)
		for j=8-1,0,-1 do	--bits
			Metatile[h][j] = Byt%2
			Byt = math.floor(Byt/2)
		end
	end
	for h=0,8-1,1 do	--bytes
		local Byt = ppu.readbyte(h+8+i*16)
		for j=8-1,0,-1 do	--bits
			Metatile[h][j] = Metatile[h][j]+Byt%2*2
			Byt = math.floor(Byt/2)
		end
	end
	PatternTable[i] = Metatile
end
end
--repeat for sprites' pattern table

local BGPalette = {}
local SpritePalette = {}
function loadBGPal()
for i=0,4-1,1 do
	BGPalette[i] = {}
	for j=0,4-1,1 do
		BGPalette[i][j] = ppu.readbyte(PPU_BG_PAL+i*4+j)
	end
end
end

function loadSpritePal()
for i=0,4-1,1 do
	SpritePalette[i] = {}
	for j=0,4-1,1 do
		SpritePalette[i][j] = ppu.readbyte(PPU_SPR_PAL+i*4+j)
	end
end
end

local cropX = 0
local cropY = 0
local cropXOldT = 0
local cropYOldT = 0
local cropXOld = 0
local cropYOld = 0
local smooth = 384
function cropLevel()
	if first > 0 then
		cropXOld = cropXOldT
		cropYOld = cropYOldT
		cropXOldT = cropX
		cropYOldT = cropY
		if memory.readbyte(Level_7Vertical) == 0 then
			if drawFullLevel then
				for i=0,ImageHeight-1,1 do
					for j=0,ImageWidth-1,1 do
						ImageOld[i][j] = Image[i][j]
					end
				end
			else
			k = memory.readbyte(Player_SpriteX)
			if k >= 128 then
				smooth = smooth - 1
			end
			if k <= 112 then
				smooth = smooth + 1
			end
			smooth = math.max(256,math.min(smooth,512))
			print("smooth",smooth)
			cropX = math.max(0,math.min(scrollX-smooth,(memory.readbyte(Level_Width)+1)*256-ImageWidth/2))--print("cropX",cropX,"scrollX-256",scrollX-256,"memory.readbyte(Level_Width)+1)*256-ImageWidth",(memory.readbyte(Level_Width)+1)*256-ImageWidth)
			cropY = 0
			for i=0,432-1,1 do
				ImageOld[i] = {}
				for j=0,1024-1,1 do
					ImageOld[i][j] = Image[i+cropY][j+cropX]
				end
			end
			end
		else
			cropX = 0
			cropY = math.min(math.max(0,scrollY-512),(memory.readbyte(Level_Width)+1)*240-ImageHeight)
			for i=0,1024-1,1 do
				ImageOld[i] = {}
				for j=0,256-1,1 do
					ImageOld[i][V1xDrawOffsetX+j] = Image[i+cropY][j+cropX]
				end
			end
		end
	end
end

function copyLevel()
	scrollXOld = scrollXOldT
	scrollYOld = scrollYOldT
	scrollXOldT = scrollX
	scrollYOldT = scrollY
	scrollX = memory.readbyte(Horz_Scroll_Hi)*256+memory.readbyte(Horz_Scroll)
	scrollY = memory.readbyte(Vert_Scroll_Hi)*256+memory.readbyte(Vert_Scroll)
	if memory.readbyte(Level_7Vertical) == 0 then
		local LvScreens = memory.readbyte(Level_Width)+1
		local LvW = LvScreens*16
		local LvH = 27
		for i=0,ImageHeight-1,1 do
			Image[i] = {}
		end
		if drawFullLevel then
		h = 0
		g = LvScreens
		ImageWidth = LvW*16
		ImageHeight = LvH*16
		else
		h=math.min(math.max(0,math.floor(scrollX/256)-2),LvScreens-6)
		g=6
		end
		for i=h,h+g-1,1 do
			for j=0,LvH-1,1 do
				for k=0,16-1,1 do
					local tile = memory.readbyte(0x6000+(i*LvH+j)*16+k)
					local colours = BGPalette[math.floor(tile/0x40)]
					for l=0,2-1,1 do
						for m=0,2-1,1 do
							local Metatile = rom.readbyte(16+rom.readbyte(TileLayoutPage_ByTileset+memory.readbyte(Tileset))*0x2000+rom.readbyte(TileLayout_ByTileset+memory.readbyte(Tileset)*2)%0x2000+l*0x200+m*0x100+tile)
							for n=0,8-1,1 do
								for o=0,8-1,1 do--print(Metatile,colours[0],colours[1],colours[2],colours[3],2,PatternTable[Metatile][n][o],3)
									Image[(j*2+m)*8+n][((i*16+k)*2+l)*8+o] = colours[PatternTable[Metatile][n][o]]
								end
							end
						end
					end
				end
			end
		end
		--print("copyLevel: h:",h)
	else
		local LvScreens = memory.readbyte(Level_Width)+1
		local LvW = 16
		local LvH = LvScreens*15
		for i=0,ImageHeight-1,1 do
			Image[i] = {}
		end
		h=math.min(math.max(0,memory.readbyte(Vert_Scroll_Hi)-32),LvH-68)
		OffsetLevelY = h
		for i=h,h+68-1,1 do
			for j=0,LvW-1,1 do
				local tile = memory.readbyte(0x6000+i*16+j)
				local colours = BGPalette[math.floor(tile/0x40)]
				for l=0,2-1,1 do
					for m=0,2-1,1 do
						local Metatile = rom.readbyte(16+rom.readbyte(TileLayoutPage_ByTileset+memory.readbyte(Tileset))*0x2000+rom.readbyte(TileLayout_ByTileset+memory.readbyte(Tileset)*2)%0x2000+l*0x200+m*0x100+tile)
						for n=0,8-1,1 do
							for o=0,8-1,1 do--print(Metatile,colours[0],colours[1],colours[2],colours[3],2,PatternTable[Metatile][n][o],3)
								Image[(i*2+m)*8+n][(j*2+l)*8+o] = colours[PatternTable[Metatile][n][o]]
							end
						end
					end
				end
			end
		end
	end
end

function exportImage()
preWriteHeader()
writeHeader()
file = io.open("map/frame"..emu.framecount()..".bmp","wb")
--io.output("map/frame"..emu.framecount()..".bmp")
--io.write(dword(FileTotalSize),dword(FileTotalSize),dword(FileTotalSize))
file:write(Header,Pal)
writeImage()
io.close()
end

function writeImage()
	if memory.readbyte(Tileset) > 0 and memory.readbyte(Raster_Effect) == 0 then
		if memory.readbyte(Level_7Vertical) == 0 then
			if drawFullLevel then
				addScreen()
				writeLevelFull()
			else
				addScreen()
				StatusBar3x()
				writeLevel2x()
			end
		else
			VaddScreen()
			VStatusBar6x()
			Vcopy2x()
			VwriteLevel()
		end
	else
		clearImageOld()
		copyScreen()
		VwriteLevel()
	end
end

function clearImageOld()
	for i=0,ImageHeight-1,1 do
		ImageOld[i] = {}
	end
end

function copyScreen()
	local nClock = os.clock()
	local t = 0
	for i=0,240-1,1 do
		for j=0,256-1,1 do
			--k,k,k,ImageOld[60+i][512+j] = emu.getscreenpixel(math.floor(j/4),math.floor(i/4),true)
			k,k,k,t = emu.getscreenpixel(j,i,true)
			local a = 60+i*4
			local b = 512+j*4
			local c = a+4-1
			local d = b+4-1
			for m=a,c,1 do
				for n=b,d,1 do
					ImageOld[m][n] = t
				end
			end
		end
	end
	print("copyScreen time:",os.clock()-nClock)
end

function writeLevelFull()
	for i=ImageHeight-1,0,-1 do
		for j=0,ImageWidth-1,1 do
			file:write(string.char(ImageOld[i][j]))
		end
	end
end

function writeLevel2x()
	local nClock = os.clock()
	for i=ImageHeight/2-1,0,-1 do
		local line = {}
		local mf = math.floor
		local sc = string.char
		h=ImageWidth/2-1
		for j=0,h,1 do
			k = sc(ImageOld[mf(i/2)][j] or 15)
			line[j*2+1] = k
			line[j*2+2] = k
		end
		line = table.concat(line)
		line = line .. line
		file:write(line)
		--print(string.len(line),#line)
	end
	print("writeLevel2x time:",os.clock()-nClock)
end

function VwriteLevel()
	local nClock = os.clock()
	for i=ImageHeight-1,0,-1 do
		local line = {}
		local sc = string.char
		for j=0,ImageWidth-1,1 do
			line[j+1] = sc(ImageOld[i][j] or 15)
		end
		file:write(table.concat(line))
	end
	print("VwriteLevel time:",os.clock()-nClock)
end

function addScreen()
	local nClock = os.clock()
	local b = true
	for i=0,192-1,1 do
		for j=8,248-1,1 do
			local t = 15
			--print(ImageOld[239][scrollXOld+j])
			--print(scrollYOld,scrollXOld,i,j)
			k,k,k,t = emu.getscreenpixel(j,i,true)
			ImageOld[scrollYOld-cropY+i][scrollXOld-cropX+j] = t
			b = b and (t == 15)
		end
	end
	if b then
		clearImageOld()
		smooth = 384
	end
	print("addScreen time:",os.clock()-nClock)
end

function VaddScreen()
	for i=0,192-1,1 do
		for j=8,256-1,1 do
			k,k,k,ImageOld[scrollYOld-OffsetLevelY+i][scrollXOld+j] = emu.getscreenpixel(j,i,true)
		end
	end
end

function StatusBar3x()
	local nClock = os.clock()
	local mf = math.floor
	for i=3*3,48*3-1 do
		for j=8*3,256*3-1,1 do
			k,k,k,ImageOld[StatusBarY+i][j] = emu.getscreenpixel(mf(j/3),192+mf(i/3),true)
		end
	end
	print("StatusBar3x time:",os.clock()-nClock)
end
function VStatusBar6x()
	for i=0,32*6-1 do
		for j=0,VStatusBarSplit*6-1,1 do
			k,k,k,ImageOld[VStatusBarY+i][j] = emu.getscreenpixel(math.floor(j/6),192+math.floor(i/6),true)
		end
	end		
end
function Vcopy2x()
	h=math.min(math.max(0,ScrollYOld-256),(memory.readbyte(Level_Width)+1)*240-540)
	for i=0,ImageHeight-1,1 do
		for j=0,512-1,1 do
			ImageOld[i][V2xDrawOffsetX-V1xDrawOffsetX+j] = ImageOld[h+math.floor(i/2)][math.floor(j/2)]
		end
	end
end
	
init()
memory.registerexecute(0xfad3, irq)
emu.registerafter(after)