From 3544cbd2789e029614d6df59ceddd4261cdd7bab Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 13 Jan 2017 18:16:10 -1000 Subject: [PATCH] Work on FRME widgets; initial DSP streaming --- DataSpec/DNAMP1/FRME.cpp | 298 +++++++++++++++++++++----- DataSpec/DNAMP1/FRME.hpp | 64 ++++-- Runtime/Audio/CDSPAudioPlayer.cpp | 63 ++++++ Runtime/Audio/CDSPAudioPlayer.hpp | 16 ++ Runtime/Audio/CMakeLists.txt | 1 + Runtime/GuiSys/CAuiMeter.cpp | 110 ++++++++++ Runtime/GuiSys/CAuiMeter.hpp | 23 +- Runtime/GuiSys/CGuiGroup.cpp | 6 +- Runtime/GuiSys/CGuiGroup.hpp | 6 +- Runtime/GuiSys/CGuiTextSupport.hpp | 12 +- Runtime/GuiSys/CInstruction.cpp | 18 +- Runtime/GuiSys/CTextExecuteBuffer.cpp | 40 ++-- Runtime/GuiSys/CTextExecuteBuffer.hpp | 4 +- hecl | 2 +- 14 files changed, 547 insertions(+), 116 deletions(-) create mode 100644 Runtime/Audio/CDSPAudioPlayer.cpp create mode 100644 Runtime/Audio/CDSPAudioPlayer.hpp diff --git a/DataSpec/DNAMP1/FRME.cpp b/DataSpec/DNAMP1/FRME.cpp index a2d0719a6..6dfe661b2 100644 --- a/DataSpec/DNAMP1/FRME.cpp +++ b/DataSpec/DNAMP1/FRME.cpp @@ -62,6 +62,7 @@ void FRME::Widget::read(athena::io::IStreamReader& __dna_reader) case SBIG('MODL'): widgetInfo.reset(new MODLInfo); break; case SBIG('METR'): widgetInfo.reset(new METRInfo); break; case SBIG('GRUP'): widgetInfo.reset(new GRUPInfo); break; + case SBIG('PANE'): widgetInfo.reset(new PANEInfo); break; case SBIG('TXPN'): widgetInfo.reset(new TXPNInfo(owner->version)); break; case SBIG('IMGP'): widgetInfo.reset(new IMGPInfo); break; case SBIG('TBGP'): widgetInfo.reset(new TBGPInfo); break; @@ -101,12 +102,14 @@ void FRME::Widget::read(athena::io::IStreamReader& __dna_reader) void FRME::Widget::write(athena::io::IStreamWriter& __dna_writer) const { /* type */ - type.write(__dna_writer); + DNAFourCC _type = widgetInfo ? widgetInfo->fourcc() : FOURCC('BWIG'); + _type.write(__dna_writer); /* header */ header.write(__dna_writer); /* widgetInfo */ - widgetInfo->write(__dna_writer); + if (widgetInfo) + widgetInfo->write(__dna_writer); /* isWorker */ __dna_writer.writeBool(isWorker); @@ -137,7 +140,8 @@ size_t FRME::Widget::binarySize(size_t __isz) const { __isz = type.binarySize(__isz); __isz = header.binarySize(__isz); - __isz = widgetInfo->binarySize(__isz); + if (widgetInfo) + __isz = widgetInfo->binarySize(__isz); if (isWorker) __isz += 4; return __isz + 67; @@ -335,22 +339,8 @@ bool FRME::Extract(const SpecBase &dataSpec, hecl::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); - os << "import bpy, math\n" + os << "import bpy, math, bmesh\n" "from mathutils import Matrix, Quaternion\n" - "bpy.types.Object.retro_widget_type = bpy.props.StringProperty(name='Retro: FRME Widget Type')\n" - "model_draw_flags = [\n" - " ('RETRO_SHADELESS', 'Shadeless', '', 0),\n" - " ('RETRO_OPAQUE', 'Opaque', '', 1),\n" - " ('RETRO_ALPHA', 'Alpha', '', 2),\n" - " ('RETRO_ADDITIVE', 'Additive', '', 3),\n" - " ('RETRO_ALPHA_ADDITIVE_OVERDRAW', 'Alpha Additive Overdraw', '', 4)]\n" - "bpy.types.Object.retro_widget_parent = bpy.props.StringProperty(name='Retro: FRME Widget Parent', description='Refers to internal frame widgets')\n" - "bpy.types.Object.retro_widget_use_anim_controller = bpy.props.BoolProperty(name='Retro: Use Animiation Conroller')\n" - "bpy.types.Object.retro_widget_default_visible = bpy.props.BoolProperty(name='Retro: Default Visible', description='Sets widget is visible by default')\n" - "bpy.types.Object.retro_widget_default_active = bpy.props.BoolProperty(name='Retro: Default Visible', description='Sets widget is cases by default')\n" - "bpy.types.Object.retro_widget_cull_faces = bpy.props.BoolProperty(name='Retro: Default Visible', description='Enables face culling')\n" - "bpy.types.Object.retro_widget_color = bpy.props.FloatVectorProperty(name='Retro: Color', description='Sets widget color', subtype='COLOR', size=4, min=0.0, max=1.0)\n" - "bpy.types.Object.retro_widget_model_draw_flags = bpy.props.EnumProperty(items=model_draw_flags, name='Retro: Model Draw Flags', default='RETRO_ALPHA')\n" "# Clear Scene\n" "for ob in bpy.data.objects:\n" " if ob.type != 'CAMERA':\n" @@ -388,8 +378,7 @@ bool FRME::Extract(const SpecBase &dataSpec, using CAMRInfo = Widget::CAMRInfo; os.format("cam = bpy.data.cameras.new(name='%s')\n" "binding = cam\n", w.header.name.c_str()); - CAMRInfo* info = static_cast(w.widgetInfo.get()); - if (info) + if (CAMRInfo* info = static_cast(w.widgetInfo.get())) { if (info->projectionType == CAMRInfo::ProjectionType::Orthographic) { @@ -402,12 +391,15 @@ bool FRME::Extract(const SpecBase &dataSpec, CAMRInfo::PerspectiveProjection* proj = static_cast(info->projection.get()); os.format("cam.type = 'PERSP'\n" "cam.lens_unit = 'FOV'\n" - "cam.angle = math.radians(%f)\n" "cam.clip_start = %f\n" "cam.clip_end = %f\n" - "bpy.context.scene.render.pixel_aspect_x = %f\n" - "bpy.context.scene.render.pixel_aspect_y = bpy.context.scene.render.pixel_aspect_x\n", - proj->fov, proj->znear, proj->zfar, proj->aspect); + "bpy.context.scene.render.resolution_x = 480 * %f\n", + proj->znear, proj->zfar, proj->aspect); + if (proj->aspect > 1.f) + os.format("cam.angle = math.atan2(%f, 1.0 / math.tan(math.radians(%f / 2.0))) * 2.0\n", + proj->aspect, proj->fov); + else + os.format("cam.angle = math.radians(%f)\n", proj->fov); } } os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; @@ -415,35 +407,130 @@ bool FRME::Extract(const SpecBase &dataSpec, else if (w.type == SBIG('LITE')) { using LITEInfo = Widget::LITEInfo; - LITEInfo* info = static_cast(w.widgetInfo.get()); - if (info) + if (LITEInfo* info = static_cast(w.widgetInfo.get())) { switch(info->type) { case LITEInfo::ELightType::LocalAmbient: - os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0\n" + os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n" "bg_node.inputs[1].default_value = %f\n", w.header.color.vec[0], w.header.color.vec[1], w.header.color.vec[2], info->distQ / 8.0); + break; + case LITEInfo::ELightType::Spot: + case LITEInfo::ELightType::Directional: + os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; default: os.format("lamp = bpy.data.lamps.new(name='%s', type='POINT')\n" "lamp.color = (%f, %f, %f)\n" + "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" + "lamp.constant_coefficient = %f\n" + "lamp.linear_coefficient = %f\n" + "lamp.quadratic_coefficient = %f\n" + "lamp.retro_light_angle_constant = %f\n" + "lamp.retro_light_angle_linear = %f\n" + "lamp.retro_light_angle_quadratic = %f\n" + "lamp.retro_light_index = %d\n" "binding = lamp\n", w.header.name.c_str(), - w.header.color.vec[0], w.header.color.vec[1], w.header.color.vec[2]); + w.header.color.vec[0], w.header.color.vec[1], w.header.color.vec[2], + info->distC, info->distL, info->distQ, + info->angC, info->angL, info->angQ, info->loadedIdx); + if (info->type == LITEInfo::ELightType::Spot) + os.format("lamp.type = 'SPOT'\n" + "lamp.spot_size = %f\n", + info->cutoff); + else if (info->type == LITEInfo::ELightType::Directional) + os << "lamp.type = 'HEMI'\n"; } } } + else if (w.type == SBIG('IMGP')) + { + using IMGPInfo = Widget::IMGPInfo; + if (IMGPInfo* info = static_cast(w.widgetInfo.get())) + { + std::string texName; + hecl::SystemString resPath; + if (info->texture) + { + texName = pakRouter.getBestEntryName(info->texture); + const nod::Node* node; + const PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(info->texture, &node); + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (txtrPath.isNone()) + { + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); + } + resPath = pakRouter.getResourceRelativePath(entry, info->texture); + } + hecl::SystemUTF8View resPathView(resPath); + os.format("if '%s' in bpy.data.images:\n" + " image = bpy.data.images['%s']\n" + "else:\n" + " image = bpy.data.images.load('''//%s''')\n" + " image.name = '%s'\n" + "material = bpy.data.materials.new('%s')\n" + "material.specular_intensity = 0.0\n" + "tex_slot = material.texture_slots.add()\n" + "tex_slot.texture = bpy.data.textures.new('%s', 'IMAGE')\n" + "tex_slot.texture.image = image\n" + "material.active_texture = tex_slot.texture\n" + "bm = bmesh.new()\n" + "verts = []\n", + texName.c_str(), texName.c_str(), + resPathView.str().c_str(), texName.c_str(), + w.header.name.c_str(), w.header.name.c_str()); + for (int i=0 ; iquadCoordCount ; ++i) + { + int ti; + if (i == 2) + ti = 3; + else if (i == 3) + ti = 2; + else + ti = i; + os.format("verts.append(bm.verts.new((%f,%f,%f)))\n", + info->quadCoords[ti].vec[0], + info->quadCoords[ti].vec[1], + info->quadCoords[ti].vec[2]); + } + os << "bm.faces.new(verts)\n" + "bm.loops.layers.uv.new('UV')\n" + "bm.verts.ensure_lookup_table()\n"; + for (int i=0 ; iuvCoordCount ; ++i) + { + int ti; + if (i == 2) + ti = 3; + else if (i == 3) + ti = 2; + else + ti = i; + os.format("bm.verts[%d].link_loops[0][bm.loops.layers.uv[0]].uv = (%f,%f)\n", i, + info->uvCoords[ti].vec[0], + info->uvCoords[ti].vec[1]); + } + os.format("binding = bpy.data.meshes.new('%s')\n" + "bm.to_mesh(binding)\n" + "bm.free()\n" + "binding.materials.append(material)\n", + w.header.name.c_str()); + } + } os.format("frme_obj = bpy.data.objects.new(name='%s', object_data=binding)\n" "parentName = '%s'\n" - "frme_obj.retro_widget_type = '%s'\n" + "frme_obj.retro_widget_type = 'RETRO_%s'\n" "frme_obj.retro_widget_use_anim_controller = %s\n" "frme_obj.retro_widget_default_visible = %s\n" "frme_obj.retro_widget_default_active = %s\n" "frme_obj.retro_widget_cull_faces = %s\n" "frme_obj.retro_widget_color = (%f,%f,%f,%f)\n" - "frme_obj.retro_widget_model_draw_flags = model_draw_flags[%i][0]\n" + "frme_obj.retro_widget_model_draw_flags = bpy.types.Object.retro_widget_model_draw_flags[1]['items'][%i][0]\n" + "frme_obj.retro_widget_is_worker = %s\n" + "frme_obj.retro_widget_worker_id = %d\n" "if parentName not in bpy.data.objects:\n" " frme_obj.retro_widget_parent = parentName\n" "else:\n" @@ -455,50 +542,147 @@ bool FRME::Extract(const SpecBase &dataSpec, w.header.defaultActive ? "True" : "False", w.header.cullFaces ? "True" : "False", w.header.color.vec[0], w.header.color.vec[1], w.header.color.vec[2], w.header.color.vec[3], - w.header.modelDrawFlags); + w.header.modelDrawFlags, + w.isWorker ? "True" : "False", + w.workerId); if (w.type == SBIG('MODL')) { using MODLInfo = FRME::Widget::MODLInfo; - MODLInfo* info = dynamic_cast(w.widgetInfo.get()); + MODLInfo* info = static_cast(w.widgetInfo.get()); hecl::ProjectPath modelPath = pakRouter.getWorking(info->model); const PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info->model, nullptr, true, true); os.linkBlend(modelPath.getAbsolutePathUTF8().c_str(), pakRouter.getBestEntryName(*cmdlE).c_str(), true); + os.format("frme_obj.retro_model_light_mask = %d\n", info->lightMask); os << "print(obj.name)\n" "copy_obj = duplicateObject(obj)\n" "copy_obj.parent = frme_obj\n" "copy_obj.hide = False\n"; } - else if (w.type == SBIG('IMGP')) + else if (w.type == SBIG('CAMR')) { - using IMGPInfo = Widget::IMGPInfo; - IMGPInfo* info = dynamic_cast(w.widgetInfo.get()); - if (info && info->texture) + os << "bpy.context.scene.camera = frme_obj\n" + "if 'Camera' in bpy.data.objects:\n" + " cam = bpy.data.objects['Camera']\n" + " bpy.context.scene.objects.unlink(cam)\n" + " bpy.data.objects.remove(cam)\n"; + } + else if (w.type == SBIG('PANE')) + { + using PANEInfo = Widget::PANEInfo; + if (PANEInfo* info = static_cast(w.widgetInfo.get())) { - std::string texName = pakRouter.getBestEntryName(info->texture); - const nod::Node* node; - const PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(info->texture, &node); - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.isNone()) - { - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, info->texture); - hecl::SystemUTF8View resPathView(resPath); - os.format("if '%s' in bpy.data.images:\n" - " image = bpy.data.images['%s']\n" - "else:\n" - " image = bpy.data.images.load('''//%s''')\n" - " image.name = '%s'\n" - "frme_obj.empty_draw_type = 'IMAGE'\n" - "frme_obj.data = image\n" - "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n", - texName.c_str(), texName.c_str(), - resPathView.str().c_str(), texName.c_str()); + os.format("frme_obj.retro_pane_dimensions = (%f,%f)\n" + "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n", + info->xDim, info->zDim, + info->scaleCenter.vec[0], + info->scaleCenter.vec[1], + info->scaleCenter.vec[2]); + } + } + else if (w.type == SBIG('TXPN')) + { + using TXPNInfo = Widget::TXPNInfo; + if (TXPNInfo* info = static_cast(w.widgetInfo.get())) + { + hecl::ProjectPath fontPath = pakRouter.getWorking(info->font, true); + hecl::ProjectPath jpFontPath; + if (frme.version >= 1) + jpFontPath = pakRouter.getWorking(info->jpnFont, true); + + os.format("frme_obj.retro_pane_dimensions = (%f,%f)\n" + "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n" + "frme_obj.retro_textpane_font_path = '%s'\n" + "frme_obj.retro_textpane_word_wrap = %s\n" + "frme_obj.retro_textpane_vertical = %s\n" + "frme_obj.retro_textpane_fill_color = (%f,%f,%f,%f)\n" + "frme_obj.retro_textpane_outline_color = (%f,%f,%f,%f)\n" + "frme_obj.retro_textpane_block_extent = (%f,%f)\n" + "frme_obj.retro_textpane_jp_font_path = '%s'\n" + "frme_obj.retro_textpane_jp_font_scale = (%d,%d)\n" + "frme_obj.retro_textpane_hjustification = bpy.types.Object.retro_textpane_hjustification[1]['items'][%d][0]\n" + "frme_obj.retro_textpane_vjustification = bpy.types.Object.retro_textpane_vjustification[1]['items'][%d][0]\n", + info->xDim, info->zDim, + info->scaleCenter.vec[0], + info->scaleCenter.vec[1], + info->scaleCenter.vec[2], + fontPath.getRelativePathUTF8().c_str(), + info->wordWrap ? "True" : "False", + info->vertical ? "True" : "False", + info->fillColor.vec[0], + info->fillColor.vec[1], + info->fillColor.vec[2], + info->fillColor.vec[3], + info->outlineColor.vec[0], + info->outlineColor.vec[1], + info->outlineColor.vec[2], + info->outlineColor.vec[3], + info->blockExtent.vec[0], + info->blockExtent.vec[1], + jpFontPath.getRelativePathUTF8().c_str(), + info->jpnPointScale[0], + info->jpnPointScale[1], + int(info->justification), + int(info->verticalJustification)); + } + } + else if (w.type == SBIG('TBGP')) + { + using TBGPInfo = Widget::TBGPInfo; + if (TBGPInfo* info = static_cast(w.widgetInfo.get())) + { + os.format("frme_obj.retro_tablegroup_elem_count = %d\n" + "frme_obj.retro_tablegroup_elem_default = %d\n" + "frme_obj.retro_tablegroup_wraparound = %s\n", + info->elementCount, info->defaultSelection, + info->selectWraparound ? "True" : "False"); + } + } + else if (w.type == SBIG('GRUP')) + { + using GRUPInfo = Widget::GRUPInfo; + if (GRUPInfo* info = static_cast(w.widgetInfo.get())) + { + os.format("frme_obj.retro_group_default_worker = %d\n", + info->defaultWorker); + } + } + else if (w.type == SBIG('SLGP')) + { + using SLGPInfo = Widget::SLGPInfo; + if (SLGPInfo* info = static_cast(w.widgetInfo.get())) + { + os.format("frme_obj.retro_slider_min = %f\n" + "frme_obj.retro_slider_max = %f\n" + "frme_obj.retro_slider_default = %f\n" + "frme_obj.retro_slider_increment = %f\n", + info->min, info->max, info->cur, info->increment); + } + } + else if (w.type == SBIG('ENRG')) + { + using ENRGInfo = Widget::ENRGInfo; + if (ENRGInfo* info = static_cast(w.widgetInfo.get())) + { + hecl::ProjectPath txtrPath = pakRouter.getWorking(info->texture); + if (txtrPath) + os.format("frme_obj.retro_energybar_texture_path = '%s'\n", + txtrPath.getRelativePathUTF8().c_str()); + } + } + else if (w.type == SBIG('METR')) + { + using METRInfo = Widget::METRInfo; + if (METRInfo* info = static_cast(w.widgetInfo.get())) + { + os.format("frme_obj.retro_meter_no_round_up = %s\n" + "frme_obj.retro_meter_max_capacity = %d\n" + "frme_obj.retro_meter_worker_count = %d\n", + info->noRoundUp ? "True" : "False", + info->maxCapacity, info->workerCount); } } diff --git a/DataSpec/DNAMP1/FRME.hpp b/DataSpec/DNAMP1/FRME.hpp index 01daba316..5b3423af6 100644 --- a/DataSpec/DNAMP1/FRME.hpp +++ b/DataSpec/DNAMP1/FRME.hpp @@ -42,11 +42,12 @@ struct FRME : BigDNA virtual void read(athena::io::IStreamReader&) {} void write(athena::io::IStreamWriter&) const {} size_t binarySize(size_t __isz) const { return __isz; } + virtual FourCC fourcc() const=0; }; std::unique_ptr widgetInfo; Value isWorker; - Value workerId; + Value workerId = 0; Value origin; Value basis[3]; Value rotationCenter; @@ -55,10 +56,16 @@ struct FRME : BigDNA Value animControllerCount; struct BWIGInfo : IWidgetInfo - { Delete _d; }; + { + Delete _d; + FourCC fourcc() const { return FOURCC('BWIG'); } + }; struct HWIGInfo : IWidgetInfo - { Delete _d; }; + { + Delete _d; + FourCC fourcc() const { return FOURCC('HWIG'); } + }; struct CAMRInfo : IWidgetInfo { @@ -99,6 +106,8 @@ struct FRME : BigDNA Value zfar; }; std::unique_ptr projection; + + FourCC fourcc() const { return FOURCC('CAMR'); } }; struct MODLInfo : IWidgetInfo @@ -115,6 +124,8 @@ struct FRME : BigDNA Value blendMode; Value lightMask; + + FourCC fourcc() const { return FOURCC('MODL'); } }; struct LITEInfo : IWidgetInfo @@ -138,20 +149,27 @@ struct FRME : BigDNA Value angQ; Value loadedIdx; Value cutoff; /* Spot only */ + + FourCC fourcc() const { return FOURCC('LITE'); } }; struct ENRGInfo : IWidgetInfo { DECL_DNA UniqueID32 texture; + + FourCC fourcc() const { return FOURCC('ENRG'); } }; struct METRInfo : IWidgetInfo { DECL_DNA - Value unk1; - Value value1; - Value value2; + Value unk1; + Value noRoundUp; + Value maxCapacity; + Value workerCount; + + FourCC fourcc() const { return FOURCC('METR'); } }; struct GRUPInfo : IWidgetInfo @@ -159,6 +177,8 @@ struct FRME : BigDNA DECL_DNA Value defaultWorker; Value unk3; + + FourCC fourcc() const { return FOURCC('GRUP'); } }; struct TBGPInfo : IWidgetInfo @@ -179,6 +199,8 @@ struct FRME : BigDNA Value unk9; Value unk10; Value unk11; + + FourCC fourcc() const { return FOURCC('TBGP'); } }; struct SLGPInfo : IWidgetInfo @@ -188,6 +210,18 @@ struct FRME : BigDNA Value max; Value cur; Value increment; + + FourCC fourcc() const { return FOURCC('SLGP'); } + }; + + struct PANEInfo : IWidgetInfo + { + DECL_DNA + Value xDim; + Value zDim; + Value scaleCenter; + + FourCC fourcc() const { return FOURCC('PANE'); } }; struct TXPNInfo : IWidgetInfo @@ -201,9 +235,9 @@ struct FRME : BigDNA NLeft, NCenter, NRight, - Seven, - Eight, - Nine + LeftMono, + CenterMono, + RightMono }; enum class VerticalJustification : atUint32 @@ -215,9 +249,9 @@ struct FRME : BigDNA NTop, NCenter, NBottom, - Seven, - Eight, - Nine + LeftMono, + CenterMono, + RightMono }; DECL_EXPLICIT_DNA @@ -239,7 +273,9 @@ struct FRME : BigDNA Value blockExtent; /* In points; converted to int by loader */ /* The following is only found in V1 */ UniqueID32 jpnFont; - Value jpnPointScale[2]; + Value jpnPointScale[2] = {}; + + FourCC fourcc() const { return FOURCC('TXPN'); } }; struct IMGPInfo : IWidgetInfo @@ -252,6 +288,8 @@ struct FRME : BigDNA Vector quadCoords; Value uvCoordCount; Vector uvCoords; + + FourCC fourcc() const { return FOURCC('IMGP'); } }; }; diff --git a/Runtime/Audio/CDSPAudioPlayer.cpp b/Runtime/Audio/CDSPAudioPlayer.cpp new file mode 100644 index 000000000..75fccba55 --- /dev/null +++ b/Runtime/Audio/CDSPAudioPlayer.cpp @@ -0,0 +1,63 @@ +#include "CDSPAudioPlayer.hpp" +#include + +namespace urde +{ + +struct SDSPStreamInfo +{ + const char* x0_fileName; + u32 x4_; + u32 x8_; + u32 xc_; + u32 x10_; + u32 x14_; + u32 x18_adpcmOffset; + u32 x1c_; + u32 x20_; + u32 x24_adpcmCur; + u32 x28_; + u32 x2c_; + u32 x30_; + u32 x34_; + u32 x38_; +}; + +struct SDSPStream +{ + bool x0_active; + u32 x4_ownerId; + SDSPStream* x8_stereoLeft; + SDSPStream* xc_stereoRight; + SDSPStreamInfo x10_info; + u8 x4c_vol; + u8 x4d_pan; + //DVDFileInfo x50_dvdHandle1; + //DVDFileInfo x8c_dvdHandle2; + u32 xc8_streamId = -1; // MusyX stream handle + u32 xcc_adpcmCur2; + std::unique_ptr xd4_ringBuffer; + u32 xd8_ringBytes = 0x11DC0; // 73152 4sec in ADPCM bytes + u32 xdc_ringSamples = 0x1f410; // 128016 4sec in samples + bool xe0_curBuffer; + u32 xe8_silent; + u8 xec_readState; // 0: NoRead 1: Read 2: ReadWrap + + void UpdateStreamVolume(u8 vol) + { + x4c_vol = vol; + if (!x0_active || xe8_silent) + return; + //sndStreamMixParameterEx(xc8_streamId, x4c_vol, x4d_pan, 0, 0, 0); + } + + void SilenceStream() + { + if (!x0_active || xe8_silent) + return; + //sndStreamMixParameterEx(xc8_streamId, 0, x4d_pan, 0, 0, 0); + xe8_silent = true; + } +}; + +} diff --git a/Runtime/Audio/CDSPAudioPlayer.hpp b/Runtime/Audio/CDSPAudioPlayer.hpp new file mode 100644 index 000000000..e1ec0cba5 --- /dev/null +++ b/Runtime/Audio/CDSPAudioPlayer.hpp @@ -0,0 +1,16 @@ +#ifndef __URDE_CDSPAUDIOPLAYER_HPP__ +#define __URDE_CDSPAUDIOPLAYER_HPP__ + +#include "RetroTypes.hpp" + +namespace urde +{ + +class CDSPAudioPlayer +{ + +}; + +} + +#endif // __URDE_CDSPAUDIOPLAYER_HPP__ diff --git a/Runtime/Audio/CMakeLists.txt b/Runtime/Audio/CMakeLists.txt index 186c97911..e8906bded 100644 --- a/Runtime/Audio/CMakeLists.txt +++ b/Runtime/Audio/CMakeLists.txt @@ -4,6 +4,7 @@ set(AUDIO_SOURCES CAudioGroupSet.hpp CAudioGroupSet.cpp CSfxManager.hpp CSfxManager.cpp CStaticAudioPlayer.hpp CStaticAudioPlayer.cpp + CDSPAudioPlayer.hpp CDSPAudioPlayer.cpp g721.c g721.h) runtime_add_list(Audio AUDIO_SOURCES) diff --git a/Runtime/GuiSys/CAuiMeter.cpp b/Runtime/GuiSys/CAuiMeter.cpp index cb77927d4..6223538f4 100644 --- a/Runtime/GuiSys/CAuiMeter.cpp +++ b/Runtime/GuiSys/CAuiMeter.cpp @@ -3,4 +3,114 @@ namespace urde { +CAuiMeter::CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, + u32 maxCapacity, u32 workerCount) +: CGuiGroup(parms, 0, false), xc4_noRoundUp(noRoundUp), + xc8_maxCapacity(maxCapacity), xcc_capacity(maxCapacity) +{ + xd4_workers.reserve(workerCount); +} + +void CAuiMeter::UpdateMeterWorkers() +{ + float scale = xd4_workers.size() / float(xc8_maxCapacity); + + int etankCap; + if (xc4_noRoundUp) + etankCap = xcc_capacity * scale; + else + etankCap = xcc_capacity * scale + 0.5f; + + int etankFill; + if (xc4_noRoundUp) + etankFill = xd0_value * scale; + else + etankFill = xd0_value * scale + 0.5f; + + for (int i=0 ; iGetWorkerWidget(0); + CGuiWidget* emptyTank = worker->GetWorkerWidget(1); + + if (i < etankFill) + { + if (fullTank) + fullTank->SetIsVisible(true); + if (emptyTank) + emptyTank->SetIsVisible(false); + } + else if (i < etankCap) + { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(true); + } + else + { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(false); + } + } +} + +void CAuiMeter::OnVisibleChange() +{ + if (GetIsVisible()) + UpdateMeterWorkers(); +} + +void CAuiMeter::SetCurrValue(s32 val) +{ + xd0_value = zeus::clamp(0, val, xcc_capacity); + UpdateMeterWorkers(); +} + +void CAuiMeter::SetCapacity(s32 cap) +{ + xcc_capacity = zeus::clamp(0, cap, xc8_maxCapacity); + xd0_value = std::min(xcc_capacity, xd0_value); + UpdateMeterWorkers(); +} + +void CAuiMeter::SetMaxCapacity(s32 cap) +{ + xc8_maxCapacity = std::max(0, cap); + xcc_capacity = std::min(xc8_maxCapacity, xcc_capacity); + xd0_value = std::min(xcc_capacity, xd0_value); + UpdateMeterWorkers(); +} + +CGuiWidget* CAuiMeter::GetWorkerWidget(int id) const +{ + return xd4_workers[id]; +} + +bool CAuiMeter::AddWorkerWidget(CGuiWidget* worker) +{ + CGuiGroup::AddWorkerWidget(worker); + if (worker->GetWorkerId() >= xd4_workers.size()) + xd4_workers.resize(worker->GetWorkerId() + 1); + xd4_workers[worker->GetWorkerId()] = static_cast(worker); + return true; +} + +CAuiMeter* CAuiMeter::Create(CGuiFrame* frame, CInputStream& in, bool flag) +{ + CGuiWidgetParms parms = ReadWidgetHeader(frame, in, flag); + in.readBool(); + bool noRoundUp = in.readBool(); + u32 maxCapacity = in.readUint32Big(); + u32 workerCount = in.readUint32Big(); + CAuiMeter* ret = new CAuiMeter(parms, noRoundUp, maxCapacity, workerCount); + ret->ParseBaseInfo(frame, in, parms); + return ret; +} + } diff --git a/Runtime/GuiSys/CAuiMeter.hpp b/Runtime/GuiSys/CAuiMeter.hpp index 58ba22d51..65801505e 100644 --- a/Runtime/GuiSys/CAuiMeter.hpp +++ b/Runtime/GuiSys/CAuiMeter.hpp @@ -1,14 +1,33 @@ #ifndef __URDE_CAUIMETER_HPP__ #define __URDE_CAUIMETER_HPP__ -#include "CGuiCompoundWidget.hpp" +#include "CGuiGroup.hpp" namespace urde { -class CAuiMeter : public CGuiCompoundWidget +class CAuiMeter : public CGuiGroup { + bool xc4_noRoundUp; + s32 xc8_maxCapacity; + s32 xcc_capacity; + s32 xd0_value = 0; + std::vector xd4_workers; + void UpdateMeterWorkers(); + public: + CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, + u32 maxCapacity, u32 workerCount); + FourCC GetWidgetTypeID() const {return FOURCC('METR');} + + void OnVisibleChange(); + void SetCurrValue(s32 val); + void SetCapacity(s32 cap); + void SetMaxCapacity(s32 cap); + CGuiWidget* GetWorkerWidget(int id) const; + bool AddWorkerWidget(CGuiWidget* worker); + + static CAuiMeter* Create(CGuiFrame* frame, CInputStream& in, bool flag); }; } diff --git a/Runtime/GuiSys/CGuiGroup.cpp b/Runtime/GuiSys/CGuiGroup.cpp index 9e853d88e..dab4faa8b 100644 --- a/Runtime/GuiSys/CGuiGroup.cpp +++ b/Runtime/GuiSys/CGuiGroup.cpp @@ -8,7 +8,7 @@ void CGuiGroup::LoadWidgetFnMap() } CGuiGroup::CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b) -: CGuiCompoundWidget(parms), xfc_selectedWorker(defaultWorker), x100_b(b) +: CGuiCompoundWidget(parms), xbc_selectedWorker(defaultWorker), xc0_b(b) { } @@ -38,12 +38,12 @@ void CGuiGroup::SelectWorkerWidget(int workerId, bool setActive, bool setVisible CGuiWidget* CGuiGroup::GetSelectedWidget() { - return GetWorkerWidget(xfc_selectedWorker); + return GetWorkerWidget(xbc_selectedWorker); } bool CGuiGroup::AddWorkerWidget(CGuiWidget* worker) { - ++xf8_workerCount; + ++xb8_workerCount; return true; } diff --git a/Runtime/GuiSys/CGuiGroup.hpp b/Runtime/GuiSys/CGuiGroup.hpp index bad82beca..60d00f13f 100644 --- a/Runtime/GuiSys/CGuiGroup.hpp +++ b/Runtime/GuiSys/CGuiGroup.hpp @@ -8,9 +8,9 @@ namespace urde class CGuiGroup : public CGuiCompoundWidget { - u32 xf8_workerCount = 0; - int xfc_selectedWorker; - bool x100_b; + u32 xb8_workerCount = 0; + int xbc_selectedWorker; + bool xc0_b; public: CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b); FourCC GetWidgetTypeID() const {return FOURCC('GRUP');} diff --git a/Runtime/GuiSys/CGuiTextSupport.hpp b/Runtime/GuiSys/CGuiTextSupport.hpp index 874ad89c5..65f2e52da 100644 --- a/Runtime/GuiSys/CGuiTextSupport.hpp +++ b/Runtime/GuiSys/CGuiTextSupport.hpp @@ -24,9 +24,9 @@ enum class EJustification NLeft, NCenter, NRight, - Seven, - Eight, - Nine + LeftMono, + CenterMono, + RightMono }; enum class EVerticalJustification @@ -38,9 +38,9 @@ enum class EVerticalJustification NTop, NCenter, NBottom, - Seven, - Eight, - Nine + TopMono, + CenterMono, + RightMono }; enum class EColorType diff --git a/Runtime/GuiSys/CInstruction.cpp b/Runtime/GuiSys/CInstruction.cpp index 45e79fa19..166f675d8 100644 --- a/Runtime/GuiSys/CInstruction.cpp +++ b/Runtime/GuiSys/CInstruction.cpp @@ -96,11 +96,11 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const case EJustification::Left: case EJustification::Full: case EJustification::NLeft: - case EJustification::Seven: + case EJustification::LeftMono: state.xd4_curX = state.x88_curBlock->x4_offsetX; break; case EJustification::Center: - case EJustification::Eight: + case EJustification::CenterMono: state.xd4_curX = state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2; break; @@ -118,7 +118,7 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const } break; case EJustification::Right: - case EJustification::Nine: + case EJustification::RightMono: state.xd4_curX = state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX - x8_curX; break; @@ -152,14 +152,14 @@ void CLineInstruction::InvokeLTR(CFontRenderState& state) const val = 0; val += inst.xc_curY; break; - case EVerticalJustification::Seven: + case EVerticalJustification::TopMono: val = state.x88_curBlock->x24_largestMonoH; break; - case EVerticalJustification::Eight: + case EVerticalJustification::CenterMono: val = (inst.xc_curY - state.x88_curBlock->x24_largestMonoH) / 2 + state.x88_curBlock->x24_largestMonoH; break; - case EVerticalJustification::Nine: + case EVerticalJustification::RightMono: val = state.x88_curBlock->x24_largestMonoH * 2 - inst.xc_curY; break; } @@ -285,21 +285,21 @@ void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const case EVerticalJustification::Top: case EVerticalJustification::Full: case EVerticalJustification::NTop: - case EVerticalJustification::Seven: + case EVerticalJustification::TopMono: state.xd8_curY = x8_offsetY; break; case EVerticalJustification::Center: case EVerticalJustification::NCenter: state.xd8_curY = x8_offsetY + (x10_blockExtentY - x30_lineY) / 2; break; - case EVerticalJustification::Eight: + case EVerticalJustification::CenterMono: state.xd8_curY = x8_offsetY + (x10_blockExtentY - x34_lineCount * x24_largestMonoH) / 2; break; case EVerticalJustification::Bottom: case EVerticalJustification::NBottom: state.xd8_curY = x8_offsetY + x10_blockExtentY - x30_lineY; break; - case EVerticalJustification::Nine: + case EVerticalJustification::RightMono: state.xd8_curY = x8_offsetY + x10_blockExtentY - x34_lineCount * x24_largestMonoH; break; } diff --git a/Runtime/GuiSys/CTextExecuteBuffer.cpp b/Runtime/GuiSys/CTextExecuteBuffer.cpp index 3437dc597..197188b91 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.cpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.cpp @@ -241,7 +241,7 @@ int CTextExecuteBuffer::WrapOneLTR(const wchar_t* str, int len) xa0_curBlock->x2c_lineX = std::max(xa0_curBlock->x2c_lineX, xa4_curLine->x8_curX); xb0_curX += w; - x0_instList.emplace(x0_instList.cend(), new CTextInstruction(str, rem)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(str, rem)); if (rem != len) StartNewLine(); @@ -251,15 +251,15 @@ int CTextExecuteBuffer::WrapOneLTR(const wchar_t* str, int len) void CTextExecuteBuffer::MoveWordLTR() { - xa4_curLine->xc_curY = std::min(xa4_curLine->xc_curY, xb8_); + xa4_curLine->xc_curY = std::min(xa4_curLine->xc_curY, xb8_curWordY); xbc_spaceDistance = 0; --xa4_curLine->x4_wordCount; TerminateLineLTR(); xa4_curLine = static_cast(x0_instList.emplace(xa8_curWordIt, - new CLineInstruction(x18_textState.x80_just, x18_textState.x84_vjust))->get()); + std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust))->get()); - x0_instList.emplace(xa8_curWordIt, new CWordInstruction()); + x0_instList.emplace(xa8_curWordIt, std::make_shared()); ++xa0_curBlock->x34_lineCount; } @@ -270,7 +270,7 @@ void CTextExecuteBuffer::StartNewLine() TerminateLine(); xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), - new CLineInstruction(x18_textState.x80_just, x18_textState.x84_vjust)); + std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust)); xbc_spaceDistance = 0; StartNewWord(); @@ -279,11 +279,11 @@ void CTextExecuteBuffer::StartNewLine() void CTextExecuteBuffer::StartNewWord() { - xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), new CWordInstruction()); + xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), std::make_shared()); xb0_curX = 0; xac_curY = 0; - xb4_ = xa4_curLine->x8_curX; - xb8_ = xa4_curLine->xc_curY; + xb4_curWordX = xa4_curLine->x8_curX; + xb8_curWordY = xa4_curLine->xc_curY; ++xa4_curLine->x4_wordCount; } @@ -313,7 +313,7 @@ void CTextExecuteBuffer::TerminateLineLTR() void CTextExecuteBuffer::AddPopState() { - x0_instList.emplace(x0_instList.cend(), new CPopStateInstruction()); + x0_instList.emplace(x0_instList.cend(), std::make_shared()); x18_textState = xc4_stateStack.back(); xc4_stateStack.pop_back(); @@ -327,7 +327,7 @@ void CTextExecuteBuffer::AddPopState() void CTextExecuteBuffer::AddPushState() { - x0_instList.emplace(x0_instList.cend(), new CPushStateInstruction()); + x0_instList.emplace(x0_instList.cend(), std::make_shared()); xc4_stateStack.push_back(x18_textState); } @@ -353,29 +353,29 @@ void CTextExecuteBuffer::AddJustification(EJustification just) void CTextExecuteBuffer::AddLineExtraSpace(s32 space) { - x0_instList.emplace(x0_instList.cend(), new CLineExtraSpaceInstruction(space)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(space)); x18_textState.x78_extraLineSpace = space; } void CTextExecuteBuffer::AddLineSpacing(float spacing) { - x0_instList.emplace(x0_instList.cend(), new CLineSpacingInstruction(spacing)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(spacing)); x18_textState.x74_lineSpacing = spacing; } void CTextExecuteBuffer::AddRemoveColorOverride(int idx) { - x0_instList.emplace(x0_instList.cend(), new CRemoveColorOverrideInstruction(idx)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(idx)); } void CTextExecuteBuffer::AddColorOverride(int idx, const CTextColor& color) { - x0_instList.emplace(x0_instList.cend(), new CColorOverrideInstruction(idx, color)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(idx, color)); } void CTextExecuteBuffer::AddColor(EColorType tp, const CTextColor& color) { - x0_instList.emplace(x0_instList.cend(), new CColorInstruction(tp, color)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(tp, color)); } void CTextExecuteBuffer::AddImage(const CFontImageDef& image) @@ -395,12 +395,12 @@ void CTextExecuteBuffer::AddImage(const CFontImageDef& image) xa0_curBlock->x2c_lineX = xa4_curLine->x8_curX; } - x0_instList.emplace(x0_instList.cend(), new CImageInstruction(image)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(image)); } void CTextExecuteBuffer::AddFont(const TToken& font) { - x0_instList.emplace(x0_instList.cend(), new CFontInstruction(font)); + x0_instList.emplace(x0_instList.cend(), std::make_shared(font)); x18_textState.x48_font = font; if (xa0_curBlock) @@ -427,7 +427,7 @@ void CTextExecuteBuffer::BeginBlock(s32 offX, s32 offY, s32 padX, s32 padY, EVerticalJustification vjust) { x0_instList.emplace(x0_instList.cend(), - new CBlockInstruction(offX, offY, padX, padY, dir, just, vjust)); + std::make_shared(offX, offY, padX, padY, dir, just, vjust)); if (x18_textState.x48_font) { @@ -451,8 +451,8 @@ void CTextExecuteBuffer::Clear() xa0_curBlock = nullptr; xa4_curLine = nullptr; xa8_curWordIt = x0_instList.begin(); - xb4_ = 0; - xb8_ = 0; + xb4_curWordX = 0; + xb8_curWordY = 0; xbc_spaceDistance = 0; } diff --git a/Runtime/GuiSys/CTextExecuteBuffer.hpp b/Runtime/GuiSys/CTextExecuteBuffer.hpp index b79182c97..354ea72d4 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.hpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.hpp @@ -27,8 +27,8 @@ class CTextExecuteBuffer std::list>::iterator xa8_curWordIt; s32 xac_curY; s32 xb0_curX; - s32 xb4_ = 0; - s32 xb8_ = 0; + s32 xb4_curWordX = 0; + s32 xb8_curWordY = 0; s32 xbc_spaceDistance = 0; bool xc0_ = false; std::list xc4_stateStack; diff --git a/hecl b/hecl index c51b6c0cd..28e95cb62 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit c51b6c0cd96225e38c43c5116a7cce333e369894 +Subproject commit 28e95cb6255cfe7334b483021ceffac4a5662b5c