#!/usr/bin/mono /home/me/Packages/IronLanguages-main-ba2094c/bin/Release/ir.exe ## Requires IronRuby $: << "/home/me/Dev/NW4RTools/NW4RTools/bin/Release" require 'NW4RTools' require 'System.Drawing' include System include NW4RTools include NW4RTools::Models brres = ResFile.new models = brres.create_model_group path = '/home/me/Games/Newer/ModelRev' reader = System::IO::StreamReader.new("#{path}/fullworld-Z20nvrc.obj") ObjImporter.ImportModel(path, reader, brres, "WorldBase", ObjImporter::LightmapType.Map) model = models["WorldBase"] alpha_tex = Texture.new alpha_bitmap = System::Drawing::Bitmap.new("#{path}/images/alphaBlender.png") alpha_tex.images = System::Array[System::Drawing::Bitmap].new([alpha_bitmap]) alpha_tex.format = TextureFormat.RGB5A3 brres.get_texture_group.add 'alphaBlender', alpha_tex # yay #model.shapes["World2_PathsPlumbing__World2_PathsPlumbing"].clr_data[0].raw_data = System::Array[Byte].new([255, 255, 255, 128]) # move paths into DrawXlu opa = model.bytecode["DrawOpa"] if model.bytecode.contains_key("DrawXlu") xlu = model.bytecode["DrawXlu"] else xlu = ByteCode.new xlu.instructions = System::Collections::Generic::List[ByteCode::Instruction].new xlu.instructions << ByteCode::DoneInstruction.new model.bytecode["DrawXlu"] = xlu end shape_array = model.shapes.to_a to_be_moved = opa.instructions.select do |insn| insn.is_a?(ByteCode::DrawShapeInstruction) and shape_array[insn.shape_i_d].key =~ /path/i end to_be_moved.each do |insn| opa.instructions.remove insn xlu.instructions.insert 0, insn end # how's this for hackiness? model.materials.each do |kvp| next unless kvp.key =~ /path/i if false mat = kvp.value # update the material mat.tex_coord_gen_count = 4 mat.chan_count = 1 mat.tev_stage_count = 4 mat.ind_stage_count = 1 mat.cull_mode = 2 mat.z_comp_loc = 1 mat.light_set_i_d = 0xFF mat.fog_i_d = 1 4.times { |i| mat.s_r_t_settings[i] = SRTSettingInfo.new } mat.chan_ctrls[0].flag_c = 0x700 # for now, we'll just add the alpha texture tex_info = TextureInfo.new tex_info.texture_name = 'alphaBlender' tex_info.wrap_s = TextureWrapType.REPEAT tex_info.wrap_t = TextureWrapType.REPEAT tex_info.min_filt = 1 tex_info.mag_filt = 1 mat.texture_infos.insert 0, tex_info # need to make sure the order is correct # now display lists. fun, fun, fun, fun pix = DisplayListWriter.new [0xF33F0000, 0x40000017, 0xFE00FFE3, 0x410034A1, 0x42000000].each do |p| pix.load_b_p_reg p end pix.end mat.pix_d_l = pix.get_buffer tc = DisplayListWriter.new tc.load_b_p_reg 0xE2000000 3.times { tc.load_b_p_reg 0xE3000000 } tc.load_b_p_reg 0xE4000000 3.times { tc.load_b_p_reg 0xE5000000 } tc.load_b_p_reg 0xE6000000 3.times { tc.load_b_p_reg 0xE7000000 } tc.add_padding 4 (0..5).each { |x| tc.load_b_p_reg 0xE0800000 | (x << 24) } tc.load_b_p_reg 0xE68FF000 tc.load_b_p_reg 0xE7800000 tc.end mat.tev_color_d_l = tc.get_buffer imas = DisplayListWriter.new imas.load_b_p_reg 0x25000000 imas.load_b_p_reg 0x26000000 imas.pad_to_size 0x40 imas.end mat.ind_mtx_and_scale_d_l = imas.get_buffer tcg = DisplayListWriter.new tcg.load_x_f_reg 0x1040, System::Array[Byte].new([0, 0, 0x52, 0x80]) tcg.load_x_f_reg 0x1050, System::Array[Byte].new([0, 0, 0, 0]) tcg.load_x_f_reg 0x1041, System::Array[Byte].new([0, 0, 0x53, 0]) tcg.load_x_f_reg 0x1051, System::Array[Byte].new([0, 0, 0, 3]) tcg.load_x_f_reg 0x1042, System::Array[Byte].new([0, 0, 0x50, 0x86]) tcg.load_x_f_reg 0x1052, System::Array[Byte].new([0, 0, 1, 6]) tcg.load_x_f_reg 0x1043, System::Array[Byte].new([0, 0, 0x50, 0x86]) tcg.load_x_f_reg 0x1053, System::Array[Byte].new([0, 0, 1, 9]) tcg.pad_to_size 0xA0 tcg.end mat.tex_coord_gen_dl = tcg.get_buffer shad = mat.shader_ref shad.tev_stage_count = 4 shad.unk1 = 0x00010203 shad.unk2 = 0xFFFFFFFF sh = DisplayListWriter.new [6, 4, 7, 0xE, 8, 0, 9, 0xC, 0xA, 5, 0xB, 0xD, 0xC, 0xA, 0xD, 0xE].each_slice(2) do |bp| sh.load_b_p_reg 0xFE00000F # BP mask sh.load_b_p_reg 0xF0000000 | (bp[0] << 24) | bp[1] end sh.load_b_p_reg 0x27FFFFFF # IREF sh.add_padding 11 sh.load_b_p_reg 0xFEFFFFF0 sh.load_b_p_reg 0xF6E338C0 sh.load_b_p_reg 0x283C9052 sh.load_b_p_reg 0xC008F8AF sh.load_b_p_reg 0xC208F80F sh.load_b_p_reg 0xC108FFD0 sh.load_b_p_reg 0xC308E270 sh.load_b_p_reg 0x10000000 sh.load_b_p_reg 0x11000000 sh.add_padding 3 sh.load_b_p_reg 0xFEFFFFF0 sh.load_b_p_reg 0xF7E33EF0 sh.load_b_p_reg 0x293C005B sh.load_b_p_reg 0xC4080A8E sh.load_b_p_reg 0xC608FFF0 sh.load_b_p_reg 0xC508E370 sh.load_b_p_reg 0xC708F070 sh.load_b_p_reg 0x12000000 sh.load_b_p_reg 0x13000000 sh.pad_to_size 0x1E0 sh.end shad.display_list = sh.get_buffer next end if false mat = kvp.value pix_dl = DisplayListWriter.new pix_dl.load_b_p_reg 0xF33F0000 pix_dl.load_b_p_reg 0x40000017 pix_dl.load_b_p_reg 0xFE00FFE3 pix_dl.load_b_p_reg 0x410034A1 pix_dl.load_b_p_reg 0x42000000 pix_dl.end mat.pix_d_l = pix_dl.get_buffer shad = mat.shader_ref dl = DisplayListWriter.new # KSEL 0 => 4 # KSEL 1 => 0xE # KSEL 2 => 0 # KSEL 3 => 0xC # KSEL 4 => 5 # KSEL 5 => 0xD # KSEL 6 => 0xA # KSEL 7 => 0xE [6, 4, 7, 0xE, 8, 0, 9, 0xC, 0xA, 5, 0xB, 0xD, 0xC, 0xA, 0xD, 0xE].each_slice(2) do |bp| dl.load_b_p_reg 0xFE00000F # BP mask dl.load_b_p_reg 0xF0000000 | (bp[0] << 24) | bp[1] end dl.load_b_p_reg 0x27FFFFFF # IREF dl.add_padding 11 shad.tev_stage_count = 3 shad.unk1 = 0x000102FF shad.unk2 = 0xFFFFFFFF dl.load_b_p_reg 0xFEFFFFF0 # BP mask dl.load_b_p_reg 0xF6E338C0 # KSel 0 dl.load_b_p_reg 0x283C0049 dl.load_b_p_reg 0xC008F8AF dl.load_b_p_reg 0xC208F80F dl.load_b_p_reg 0xC108FFD0 dl.load_b_p_reg 0xC308E270 dl.load_b_p_reg 0x10000000 # IND_CMD 0 dl.load_b_p_reg 0x11000000 # IND_CMD 1 dl.add_padding 3 dl.load_b_p_reg 0xFEFFFFF0 dl.load_b_p_reg 0xF7003EF0 dl.load_b_p_reg 0x293BF052 dl.load_b_p_reg 0xC4080A8E dl.add_padding 5 dl.load_b_p_reg 0xC508E370 dl.add_padding 5 dl.load_b_p_reg 0x12000000 dl.pad_to_size 0x1E0 dl.end shad.display_list = dl.get_buffer next end # modify it! # first off, we'll disable lightmaps and see how that goes mat = kvp.value tex_infos = mat.texture_infos.reject { |x| x.texture_name =~ /lm_.*/ } mat.texture_infos = System::Collections::Generic::List[TextureInfo].new tex_infos.each { |x| mat.texture_infos.add x } mat.tex_coord_gen_count = 1 mat.chan_count = 1 mat.tev_stage_count = 2 mat.ind_stage_count = 0 mat.cull_mode = 2 # oops, case conversion fail right there mat.light_set_i_d = 1 pix_dl = DisplayListWriter.new pix_dl.load_b_p_reg 0xF31EFF80 pix_dl.load_b_p_reg 0x40000017 pix_dl.load_b_p_reg 0xFE00FFE3 pix_dl.load_b_p_reg 0x410034A0 #BlendMode, must analyse this #pix_dl.load_b_p_reg 0x4100F281 pix_dl.load_b_p_reg 0x42000000 pix_dl.end mat.pix_d_l = pix_dl.get_buffer tc_dl = DisplayListWriter.new tc_dl.load_b_p_reg 0xE20000FF 3.times { tc_dl.load_b_p_reg 0xE30FF0FF } tc_dl.load_b_p_reg 0xE4000000 3.times { tc_dl.load_b_p_reg 0xE5000000 } tc_dl.load_b_p_reg 0xE6000000 3.times { tc_dl.load_b_p_reg 0xE7000000 } tc_dl.add_padding 4 (0..7).each { |x| tc_dl.load_b_p_reg 0xE0800000 | (x << 24) } # add this tc_dl.load_b_p_reg 0xE6080080 3.times { tc_dl.load_b_p_reg 0xE7080080 } tc_dl.pad_to_size 0x80 tc_dl.end mat.tev_color_d_l = tc_dl.get_buffer imas_dl = DisplayListWriter.new imas_dl.load_b_p_reg 0x25000000 imas_dl.load_b_p_reg 0x26000000 imas_dl.add_padding 54 imas_dl.end mat.ind_mtx_and_scale_d_l = imas_dl.get_buffer tcg_dl = DisplayListWriter.new tcg_dl.load_x_f_reg 0x1040, System::Array[Byte].new([0, 0, 0x52, 0x80]) tcg_dl.load_x_f_reg 0x1050, System::Array[Byte].new([0, 0, 0, 0]) tcg_dl.pad_to_size 0xA0 tcg_dl.end mat.tex_coord_gen_dl = tcg_dl.get_buffer shad = mat.shader_ref dl = DisplayListWriter.new # KSEL 0 => 4 # KSEL 1 => 0xE # KSEL 2 => 0 # KSEL 3 => 0xC # KSEL 4 => 5 # KSEL 5 => 0xD # KSEL 6 => 0xA # KSEL 7 => 0xE [6, 4, 7, 0xE, 8, 0, 9, 0xC, 0xA, 5, 0xB, 0xD, 0xC, 0xA, 0xD, 0xE].each_slice(2) do |bp| dl.load_b_p_reg 0xFE00000F # BP mask dl.load_b_p_reg 0xF0000000 | (bp[0] << 24) | bp[1] end dl.load_b_p_reg 0x27FFFFFF # IREF dl.add_padding 11 shad.tev_stage_count = 2 shad.unk1 = 0x00FFFFFF shad.unk2 = 0xFFFFFFFF dl.load_b_p_reg 0xFEFFFFF0 # BP mask dl.load_b_p_reg 0xF6E338C0 # KSel 0 dl.load_b_p_reg 0x2803F040 # TREF 0 - includes stages 0 and 1 # Stage 0: Map 0, Coord 0, Texture Enabled, Channel 0 # Stage 1: Map 7, Coord 7, Texture Disabled, Channel 0 dl.load_b_p_reg 0xC008F8AF # TEV_COLOR_ENV 0 # a = GX_CC_ZERO, b = GX_CC_TEXC, c = GX_CC_RASC, d = GX_CC_ZERO # bias = GX_TB_ZERO, op = GX_TEV_ADD, clamp = GX_TRUE, scale = GX_CS_SCALE_1, dest = GX_TEVPREV dl.load_b_p_reg 0xC208F20F # TEV_COLOR_ENV 1 # a = GX_CC_ZERO, b = GX_CC_C0, c = GX_CC_CPREV, d = GX_CC_ZERO # bias = GX_TB_ZERO, op = GX_TEV_ADD, clamp = GX_TRUE, scale = GX_CS_SCALE_1, dest = GX_TEVPREV dl.load_b_p_reg 0xC108F2F0 # TEV_ALPHA_ENV 0 # a = GX_CA_ZERO, b = GX_CA_TEXA, c = GX_CA_RASA, d = GX_CA_ZERO # bias = GX_TB_ZERO, op = GX_TEV_ADD, clamp = GX_TRUE, scale = GX_CS_SCALE_1, dest = GX_TEVPREV dl.load_b_p_reg 0xC3081FF0 # TEV_ALPHA_ENV 1 # a = GX_CA_APREV, b = GX_CA_ZERO, c = GX_CA_ZERO, d = GX_CA_ZERO # bias = GX_TB_ZERO, op = GX_TEV_ADD, clamp = GX_TRUE, scale = GX_CS_SCALE_1, dest = GX_TEVPREV dl.load_b_p_reg 0x10000000 # IND_CMD 0 dl.load_b_p_reg 0x11000000 # IND_CMD 1 dl.pad_to_size 0x1E0 dl.end shad.display_list = dl.get_buffer end final_data = BrresWriter.write_file(brres) System::IO::File.write_all_bytes("#{path}/MMFullWorld_mod.brres", final_data)