[runtime] bug & crash fixes (#1211)

* bug & crash fixes

* relax fog hack slightly

* buff particles more

* borderless hack

* tone down sprite hack

* int consts in `deftype` + increase sparticle queue

* move a menu button around

* clang + test fixes

* less confusing image

* add test for new deftype feature
This commit is contained in:
ManDude 2022-03-02 01:15:15 +00:00 committed by GitHub
parent 68a1f2d012
commit 3a54a521e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 109 additions and 54 deletions

View file

@ -10,12 +10,9 @@
/*!
* Missing Features
* - Bitfields
* - Int128 children
* - Refer to yourself (structure/basic only)
* - Method List
* - Evaluate constants.
*
*/
namespace {
@ -80,7 +77,10 @@ double get_float(const goos::Object& obj) {
throw std::runtime_error(obj.print() + " was supposed to be an number, but isn't");
}
void add_field(StructureType* structure, TypeSystem* ts, const goos::Object& def) {
void add_field(StructureType* structure,
TypeSystem* ts,
const goos::Object& def,
std::unordered_map<goos::HeapObject*, goos::Object>& constants) {
auto rest = &def;
auto name = symbol_string(car(rest));
@ -101,6 +101,10 @@ void add_field(StructureType* structure, TypeSystem* ts, const goos::Object& def
if (car(rest).is_int()) {
array_size = car(rest).integer_obj.value;
rest = cdr(rest);
} else if (car(rest).is_symbol() &&
constants.find((car(rest)).as_symbol()) != constants.end()) {
array_size = get_int(constants[(car(rest)).as_symbol()]);
rest = cdr(rest);
}
while (!rest->is_empty_list()) {
@ -114,6 +118,15 @@ void add_field(StructureType* structure, TypeSystem* ts, const goos::Object& def
} else if (opt_name == ":offset") {
offset_override = get_int(car(rest));
rest = cdr(rest);
} else if (opt_name == ":overlay-at") {
auto field_name = symbol_string(car(rest));
Field overlay_field;
if (!structure->lookup_field(field_name, &overlay_field)) {
throw std::runtime_error(
fmt::format("Field {} not found to overlay for {}", field_name, name));
}
offset_override = overlay_field.offset();
rest = cdr(rest);
} else if (opt_name == ":score") {
score = get_float(car(rest));
rest = cdr(rest);
@ -280,12 +293,14 @@ struct StructureDefResult {
bool always_stack_singleton = false;
};
StructureDefResult parse_structure_def(StructureType* type,
TypeSystem* ts,
const goos::Object& fields,
const goos::Object& options) {
StructureDefResult parse_structure_def(
StructureType* type,
TypeSystem* ts,
const goos::Object& fields,
const goos::Object& options,
std::unordered_map<goos::HeapObject*, goos::Object>& constants) {
StructureDefResult result;
for_each_in_list(fields, [&](const goos::Object& o) { add_field(type, ts, o); });
for_each_in_list(fields, [&](const goos::Object& o) { add_field(type, ts, o, constants); });
TypeFlags flags;
flags.heap_base = 0;
@ -530,7 +545,15 @@ TypeSpec parse_typespec(const TypeSystem* type_system, const goos::Object& src)
return {};
}
DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) {
DeftypeResult parse_deftype(const goos::Object& deftype,
TypeSystem* ts,
std::unordered_map<goos::HeapObject*, goos::Object>* constants) {
std::unordered_map<goos::HeapObject*, goos::Object> no_consts;
auto& constants_to_use = no_consts;
if (constants != nullptr) {
constants_to_use = *constants;
}
auto iter = &deftype;
auto& type_name_obj = car(iter);
@ -545,7 +568,7 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) {
throw std::runtime_error("deftype must be given a symbol as the type name");
}
auto name = type_name_obj.as_symbol()->name;
auto& name = type_name_obj.as_symbol()->name;
auto parent_type_name = deftype_parent_list(parent_list_obj);
auto parent_type = ts->make_typespec(parent_type_name);
DeftypeResult result;
@ -561,7 +584,8 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) {
}
new_type->inherit(pto);
ts->forward_declare_type_as(name, "basic");
auto sr = parse_structure_def(new_type.get(), ts, field_list_obj, options_obj);
auto sr =
parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants_to_use);
result.flags = sr.flags;
result.create_runtime_type = sr.generate_runtime_type;
if (sr.pack_me) {
@ -592,7 +616,8 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) {
ASSERT(pto);
new_type->inherit(pto);
ts->forward_declare_type_as(name, "structure");
auto sr = parse_structure_def(new_type.get(), ts, field_list_obj, options_obj);
auto sr =
parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants_to_use);
result.flags = sr.flags;
result.create_runtime_type = sr.generate_runtime_type;
if (sr.pack_me) {

View file

@ -16,5 +16,8 @@ struct DeftypeResult {
bool create_runtime_type = true;
};
DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts);
DeftypeResult parse_deftype(
const goos::Object& deftype,
TypeSystem* ts,
std::unordered_map<goos::HeapObject*, goos::Object>* constants = nullptr);
TypeSpec parse_typespec(const TypeSystem* type_system, const goos::Object& src);

View file

@ -29610,7 +29610,7 @@
(define-extern swamp-rat-nest-spawn-rat (function (pointer process) :behavior swamp-rat-nest)) ;; this needs a t2 symbol arg to pass to swamp-rat-init-from-other...but
(define-extern swamp-rat-nest-dummy-init-by-other (function swamp-rat-nest-dummy none :behavior swamp-rat-nest-dummy))
(define-extern swamp-rat-nest-pick-spawn-joint (function int :behavior swamp-rat-nest))
(define-extern swamp-rat-nest-dummy-take-damage (function int int :behavior swamp-rat-nest-dummy))
(define-extern swamp-rat-nest-dummy-take-damage (function int none :behavior swamp-rat-nest-dummy))
(define-extern swamp-rat-nest-dummy-draw-spawn-joints (function symbol :behavior swamp-rat-nest-dummy))
(define-extern swamp-rat-nest-dummy-event-handler (function process int symbol event-message-block object :behavior swamp-rat-nest-dummy))
(define-extern swamp-rat-nest-default-event-handler (function process int symbol event-message-block object :behavior swamp-rat-nest))

View file

@ -46,7 +46,7 @@ void for_each_in_list(goos::Object& list, T f) {
void DecompilerTypeSystem::parse_type_defs(const std::vector<std::string>& file_path) {
auto read = m_reader.read_from_file(file_path);
auto data = cdr(read);
auto& data = cdr(read);
for_each_in_list(data, [&](goos::Object& o) {
try {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -94,6 +94,12 @@ int GfxDisplay::width() {
int GfxDisplay::height() {
int h;
m_renderer->display_size(this, NULL, &h);
#ifdef _WIN32
if (fullscreen_mode() == 2) {
// windows borderless hack
h--;
}
#endif
return h;
}

View file

@ -43,7 +43,7 @@ void GLAPIENTRY opengl_error_callback(GLenum source,
} else if (severity == GL_DEBUG_SEVERITY_HIGH) {
lg::error("[{}] OpenGL error 0x{:X} S{:X} T{:X}: {}", g_current_render, id, source, type,
message);
ASSERT(false);
// ASSERT(false);
}
}

View file

@ -67,7 +67,7 @@ class OpenGlDebugGui {
float target_fps = 60.f;
bool experimental_accurate_lag = false;
bool sleep_in_frame_limiter = true;
bool small_profiler = true;
bool small_profiler = false;
private:
FrameTimeRecorder m_frame_timer;

View file

@ -8,7 +8,7 @@ uniform float alpha_reject;
uniform float color_mult;
uniform vec4 fog_color;
in flat uvec4 tex_info;
in flat uvec2 tex_info;
in float fog;
layout (binding = 0) uniform sampler2D tex_T0;

View file

@ -78,7 +78,7 @@ void main() {
fragment_color.w *= 2;
// fog hack
if (fragment_color.r < 0.01 && fragment_color.g < 0.01 && fragment_color.b < 0.01) {
if (fragment_color.r < 0.0075 && fragment_color.g < 0.0075 && fragment_color.b < 0.0075) {
fogginess = 0;
}

View file

@ -4453,7 +4453,6 @@
(float-var "Actor pause dist" #f ,(dm-lambda-meters-var (-> *ACTOR-bank* pause-dist)) 20 1 #t 0 10000 1)
(flag "Heap status" #f ,(dm-lambda-boolean-flag (-> *pc-settings* display-heap-status)))
(flag "Bug report" #f ,(dm-lambda-boolean-flag (-> *pc-settings* display-bug-report)))
(flag "Force progress" #f ,(dm-lambda-boolean-flag (-> *pc-settings* progress-force?)))
(menu "Mood override"
(function "-- SIMPLE OVERRIDE" #f nothing)
(flag "Palette 0" 0 dm-mood-override-palette-pick-func)
@ -4477,6 +4476,7 @@
(float-fixed-var "Palette 7 Amt" 7 dm-mood-palette-float 0 10 #t 0 1000 3)
)
)
(flag "Force progress" #f ,(dm-lambda-boolean-flag (-> *pc-settings* progress-force?)))
)
))
(other-menu (-> (the-as debug-menu-item-submenu other-menu-node) submenu))

View file

@ -240,7 +240,7 @@
"demo-start"
)
(*debug-segment*
(#if (user? dass) "village1-warp" "village1-hut")
"village1-hut"
)
(else
"title-start"

View file

@ -2153,21 +2153,25 @@
)
;; init art buffers and engines
(defconstant FOREGROUND_DRAW_MAX_COUNT_0 (* PROCESS_HEAP_MULT 280))
(defconstant FOREGROUND_DRAW_MAX_COUNT_2 (* PROCESS_HEAP_MULT 16))
(defconstant DEFAULT_DRAW_MAX_COUNT_0 (* PROCESS_HEAP_MULT 280))
(defconstant DEFAULT_DRAW_MAX_COUNT_2 (* PROCESS_HEAP_MULT 10))
(when (zero? (-> *level* level0 art-group))
(let ((lev-group *level*))
(set! (-> lev-group vis?) #f)
(set! (-> lev-group loading-level) (-> lev-group level-default))
(set! (-> lev-group level0 art-group) (new 'global 'load-dir-art-group 50 (-> lev-group level0)))
(set! (-> lev-group level0 foreground-draw-engine 0) (new 'global 'engine 'draw 280))
(set! (-> lev-group level0 foreground-draw-engine 1) (new 'global 'engine 'draw 280))
(set! (-> lev-group level0 foreground-draw-engine 2) (new 'global 'engine 'draw 16))
(set! (-> lev-group level0 foreground-draw-engine 0) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_0))
(set! (-> lev-group level0 foreground-draw-engine 1) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_0))
(set! (-> lev-group level0 foreground-draw-engine 2) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_2))
(set! (-> lev-group level1 art-group) (new 'global 'load-dir-art-group 50 (-> lev-group level1)))
(set! (-> lev-group level1 foreground-draw-engine 0) (new 'global 'engine 'draw 280))
(set! (-> lev-group level1 foreground-draw-engine 1) (new 'global 'engine 'draw 280))
(set! (-> lev-group level1 foreground-draw-engine 2) (new 'global 'engine 'draw 16))
(set! (-> lev-group level1 foreground-draw-engine 0) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_0))
(set! (-> lev-group level1 foreground-draw-engine 1) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_0))
(set! (-> lev-group level1 foreground-draw-engine 2) (new 'global 'engine 'draw FOREGROUND_DRAW_MAX_COUNT_2))
(set! (-> lev-group level-default art-group) (new 'global 'load-dir-art-group 50 (-> lev-group level1)))
(set! (-> lev-group level-default foreground-draw-engine 0) (new 'global 'engine 'draw 280))
(set! (-> lev-group level-default foreground-draw-engine 1) (new 'global 'engine 'draw 10))
(set! (-> lev-group level-default foreground-draw-engine 0) (new 'global 'engine 'draw DEFAULT_DRAW_MAX_COUNT_0))
(set! (-> lev-group level-default foreground-draw-engine 1) (new 'global 'engine 'draw DEFAULT_DRAW_MAX_COUNT_2))
(set! (-> lev-group level0 other) (-> lev-group level1))
(set! (-> lev-group level1 other) (-> lev-group level0))
(set! (-> lev-group level-default other) #f)

View file

@ -637,6 +637,9 @@
(format file " (use-vis? ~A)~%" (-> obj use-vis?))
(format file " (skip-movies? ~A)~%" (-> obj skip-movies?))
(format file " (discord-rpc? ~A)~%" (-> obj discord-rpc?))
(format file " (camera-hflip? ~A)~%" (-> obj camera-hflip?))
(format file " (camera-vflip? ~A)~%" (-> obj camera-vflip?))
(format file " (money-starburst? ~A)~%" (-> obj money-starburst?))
(format file " (force-actors? ~A)~%" (-> obj force-actors?))
(format file " (subtitles? ~A)~%" (-> obj subtitles?))
(format file " (hinttitles? ~A)~%" (-> obj hinttitles?))

View file

@ -135,6 +135,10 @@
;; launch queue
;;;;;;;;;;;;;;;;;;;;;;;
;(#if (not PC_BIG_MEMORY)
(defconstant SPARTICLE_QUEUE_SIZE 32)
;(defconstant SPARTICLE_QUEUE_SIZE 80))
(deftype sp-queued-launch-particles (structure)
((sp-system sparticle-system :offset-assert 0)
(sp-launcher sparticle-launcher :offset-assert 4)
@ -147,7 +151,7 @@
(deftype sp-launch-queue (basic)
((in-use int32 :offset-assert 4)
(queue sp-queued-launch-particles 32 :inline :offset-assert 16)
(queue sp-queued-launch-particles SPARTICLE_QUEUE_SIZE :inline :offset-assert 16)
)
:method-count-assert 9
:size-assert #x410
@ -224,7 +228,7 @@
(let ((v1-0 *sp-launch-queue*))
;; make sure we have room in the queue
(when (= (-> v1-0 in-use) 32)
(when (= (-> v1-0 in-use) SPARTICLE_QUEUE_SIZE)
(format 0 "ERROR: sp-launch-particles called during processing, and queue is full~%")
(return 0)
)
@ -857,15 +861,13 @@
(defmethod create-launch-control sparticle-launch-group ((obj sparticle-launch-group) (arg0 process))
"create a launch-control to hold the state of the particles. stored on the process heap."
(let ((gp-0 (the-as object (new 'process 'sparticle-launch-control (-> obj length)))))
(when (zero? (the-as sparticle-launch-control gp-0))
(let ((gp-0 (the-as sparticle-launch-control (new 'process 'sparticle-launch-control (-> obj length)))))
(when (zero? gp-0)
(go process-drawable-art-error "memory")
(set! gp-0 0)
(goto cfg-4)
(return (the-as sparticle-launch-control 0))
)
(initialize (the-as sparticle-launch-control gp-0) obj arg0)
(label cfg-4)
(the-as sparticle-launch-control gp-0)
(initialize gp-0 obj arg0)
gp-0
)
)
@ -931,7 +933,12 @@
)
;; can we see it?
(sphere-in-view-frustum? (the-as sphere gp-1))
(#if (not PC_PORT)
(sphere-in-view-frustum? (the-as sphere gp-1))
;; pc port : launchers have larger bsphere if you have pc rendering on and ps2 parts off
(and (not (and (-> *pc-settings* ps2-parts?) (-> *pc-settings* use-vis?)))
(sphere-in-view-frustum? (the-as sphere (let ((bsph (new-stack-vector0))) (vector-copy! bsph gp-1) (*! (-> bsph w) 4.0) bsph))))
)
)
)
)
@ -984,7 +991,8 @@
;; pc hack for more particles.
(with-pc
(if (not (-> *pc-settings* ps2-parts?)) (/! f30-0 128.0)))
(if (and (> (-> *sprite-array-2d* num-sprites 0) 1920) (not (-> *pc-settings* ps2-parts?)))
(/! f30-0 256.0)))
;; loop over particles in the group.
(let ((s2-1 (-> obj length)))

View file

@ -158,6 +158,8 @@
)
(set! (-> obj particles s5-0 pos z) (-> obj particles s5-0 init-pos z))
)
(#when PC_PORT
(if (= *cheat-mode* 'camera) (set! (-> obj particles s5-0 pos x) 1024.0)))
(if (> (-> obj particles s5-0 part matrix) 0)
(set-vector!
(sprite-get-user-hvdf (-> obj particles s5-0 part matrix))

View file

@ -699,10 +699,8 @@
(+! (-> self parent-process 0 rat-count) (-> self parent-process 0 defensive-rat-count))
(set! (-> self parent-process 0 spawn-period) 600.0)
)
(let ((v0-0 (- (-> self parent-process 0 hit-points) arg0)))
(set! (-> self parent-process 0 hit-points) v0-0)
v0-0
)
(set! (-> self parent-process 0 hit-points) (- (-> self parent-process 0 hit-points) arg0))
(none)
)
(defbehavior swamp-rat-nest-dummy-event-handler swamp-rat-nest-dummy ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))

View file

@ -362,7 +362,7 @@ Val* Compiler::compile_deftype(const goos::Object& form, const goos::Object& res
(void)env;
// parse the type definition and add to the type system
auto result = parse_deftype(rest, &m_ts);
auto result = parse_deftype(rest, &m_ts, &m_global_constants);
// look up the type name
auto kv = m_symbol_types.find(result.type.base_type());

View file

@ -768,16 +768,15 @@
)
;; definition for function swamp-rat-nest-dummy-take-damage
;; INFO: Return type mismatch int vs none.
(defbehavior swamp-rat-nest-dummy-take-damage swamp-rat-nest-dummy ((arg0 int))
(when (not (-> self parent-process 0 damaged))
(set! (-> self parent-process 0 damaged) #t)
(+! (-> self parent-process 0 rat-count) (-> self parent-process 0 defensive-rat-count))
(set! (-> self parent-process 0 spawn-period) 600.0)
)
(let ((v0-0 (- (-> self parent-process 0 hit-points) arg0)))
(set! (-> self parent-process 0 hit-points) v0-0)
v0-0
)
(set! (-> self parent-process 0 hit-points) (- (-> self parent-process 0 hit-points) arg0))
(none)
)
;; definition for function swamp-rat-nest-dummy-event-handler

View file

@ -47,7 +47,7 @@ TEST(TypeSystemReverse, NestedInlineWeird) {
ts.add_builtin_types();
goos::Reader reader;
auto add_type = [&](const std::string& str) {
auto in = reader.read_from_string(str).as_pair()->cdr.as_pair()->car.as_pair()->cdr;
auto& in = reader.read_from_string(str).as_pair()->cdr.as_pair()->car.as_pair()->cdr;
parse_deftype(in, &ts);
};
@ -474,13 +474,14 @@ TEST(Deftype, deftype) {
TypeSystem ts;
ts.add_builtin_types();
std::string input =
"(deftype my-type (basic) ((f1 int64) (f2 string) (f3 int8) (f4 type :inline)))";
"(deftype my-type (basic) ((f1 int64) (f2 string) (f3 int8) (f4 type :inline) (f5 uint64 "
":overlay-at f1)))";
goos::Reader reader;
auto in = reader.read_from_string(input).as_pair()->cdr.as_pair()->car.as_pair()->cdr;
auto& in = reader.read_from_string(input).as_pair()->cdr.as_pair()->car.as_pair()->cdr;
auto result = parse_deftype(in, &ts);
auto& f = dynamic_cast<StructureType*>(ts.lookup_type(result.type))->fields();
EXPECT_EQ(f.size(), 5);
EXPECT_EQ(f.size(), 6);
auto& tf = f.at(0);
EXPECT_EQ(tf.name(), "type");
@ -511,6 +512,12 @@ TEST(Deftype, deftype) {
EXPECT_EQ(f4.offset(), 32);
EXPECT_EQ(f4.type().print(), "type");
EXPECT_EQ(f4.is_inline(), true);
auto& f5 = f.at(5);
EXPECT_EQ(f5.name(), "f5");
EXPECT_EQ(f5.offset(), f1.offset());
EXPECT_EQ(f5.type().print(), "uint64");
EXPECT_EQ(f5.is_inline(), false);
}
// TODO - a big test to make sure all the builtin types are what we expect.