mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
2395 lines
92 KiB
Common Lisp
2395 lines
92 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: game-save.gc
|
|
;; name in dgo: game-save
|
|
;; dgos: GAME, ENGINE
|
|
|
|
;; The game-save system implements the "background autosave" feature.
|
|
|
|
;; The process works like this:
|
|
;; - The useful parts of game-info are packed into a game-save (all at once)
|
|
;; - The auto-save process runs a state machine to write this to memory card.
|
|
;; - Additionally, the main loop calls mc-run to run the C++ memory card state machine.
|
|
|
|
;; Having two state machines, one in C++ and one in GOAL is kind of a questionable and confusing design.
|
|
|
|
;; version identifier
|
|
(defconstant SAVE_VERSION 1)
|
|
|
|
;; the C++ memory card functions also use these codes.
|
|
(defenum mc-status-code
|
|
:type uint32
|
|
(busy 0)
|
|
(ok 1)
|
|
(bad-handle 2)
|
|
(format-failed 3)
|
|
(internal-error 4)
|
|
(write-error 5)
|
|
(read-error 6)
|
|
(new-game 7)
|
|
(no-memory 8)
|
|
(no-card 9)
|
|
(no-last 10)
|
|
(no-format 11)
|
|
(no-file 12)
|
|
(no-save 13)
|
|
(no-space 14)
|
|
(bad-version 15)
|
|
(no-process 16)
|
|
(no-auto-save 17)
|
|
)
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; state serialization
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; identifier for game save fields
|
|
(defenum game-save-elt
|
|
:type uint16
|
|
(name 100)
|
|
(base-time 101)
|
|
(real-time 102)
|
|
(game-time 103)
|
|
(integral-time 104)
|
|
(continue 200)
|
|
(life 201)
|
|
(money 202)
|
|
(money-total 203)
|
|
(moeny-per-level 204)
|
|
(buzzer-total 205)
|
|
(fuel-cell 206)
|
|
(death-movie-tick 207)
|
|
(task-list 300)
|
|
(perm-list 301)
|
|
(hint-list 303)
|
|
(text-list 304)
|
|
(level-open-list 305)
|
|
(total-deaths 400)
|
|
(continue-deaths 401)
|
|
(fuel-cell-deaths 402)
|
|
(game-start-time 403)
|
|
(continue-timke 404) ;; typo in game
|
|
(death-time 405)
|
|
(hit-time 406)
|
|
(fuel-cell-pickup-time 407)
|
|
(continue-time 408)
|
|
(fuel-cell-time 409)
|
|
(enter-level-time 410)
|
|
(deaths-per-level 411)
|
|
(death-pos 412)
|
|
(auto-save-count 413)
|
|
(in-level-time 414)
|
|
(sfx-volume 500)
|
|
(music-volume 501)
|
|
(dialog-volume 502)
|
|
(language 503)
|
|
(screenx 504)
|
|
(screeny 505)
|
|
(vibration 506)
|
|
(play-hints 507)
|
|
(video-mode 508)
|
|
(aspect-ratio 509)
|
|
)
|
|
|
|
;; the game save is a bunch of "game-save-tag"s
|
|
;; the elt-type field identifies what it is.
|
|
;; the data may be stored in one of the user fields, or
|
|
;; may be stored after the tag itself.
|
|
;; the count/size fields determine how big it is.
|
|
|
|
(deftype game-save-tag (structure)
|
|
((user-object object 2 :offset-assert 0)
|
|
(user-uint64 uint64 :offset 0)
|
|
(user-float0 float :offset 0)
|
|
(user-float float 2 :offset 0)
|
|
(user-int32 int32 2 :offset 0)
|
|
(user-uint32 uint32 2 :offset 0)
|
|
(user-int16 int16 4 :offset 0)
|
|
(user-uint16 uint16 4 :offset 0)
|
|
(user-int8 int8 8 :offset 0)
|
|
(user-int80 int8 :offset 0)
|
|
(user-int81 int8 :offset 1)
|
|
(user-uint8 uint8 8 :offset 0)
|
|
(elt-count int32 :offset-assert 8)
|
|
(elt-size uint16 :offset-assert 12)
|
|
(elt-type game-save-elt :offset-assert 14)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x10
|
|
:flag-assert #x900000010
|
|
)
|
|
|
|
;; A game-save is a dynamic type that contains the full save.
|
|
;; it contains common metadata plus all the tags
|
|
;; the common metadata is used to display info about a save, without needing to
|
|
;; fully unpack the data stored in the tags.
|
|
(deftype game-save (basic)
|
|
((version int32 :offset-assert 4)
|
|
(allocated-length int32 :offset-assert 8)
|
|
(length int32 :offset-assert 12)
|
|
(info-int32 int32 16 :offset-assert 16)
|
|
(info-int8 int8 64 :offset 16)
|
|
(level-index int32 :offset 16)
|
|
(fuel-cell-count float :offset 20)
|
|
(money-count float :offset 24)
|
|
(buzzer-count float :offset 28)
|
|
(completion-percentage float :offset 32)
|
|
(minute uint8 :offset 36)
|
|
(hour uint8 :offset 37)
|
|
(week uint8 :offset 38)
|
|
(day uint8 :offset 39)
|
|
(month uint8 :offset 40)
|
|
(year uint8 :offset 41)
|
|
(new-game int32 :offset 44)
|
|
(tag game-save-tag :inline :dynamic :offset-assert 80)
|
|
)
|
|
:method-count-assert 12
|
|
:size-assert #x50
|
|
:flag-assert #xc00000050
|
|
(:methods
|
|
(new (symbol type int) _type_ 0)
|
|
(save-to-file (_type_ string) _type_ 9)
|
|
(load-from-file! (_type_ string) _type_ 10)
|
|
(debug-print (_type_ symbol) _type_ 11)
|
|
)
|
|
)
|
|
|
|
(defmethod asize-of game-save ((obj game-save))
|
|
"Get the size in memory of the save"
|
|
(the-as int (+ (-> game-save size) (the-as uint (-> obj allocated-length))))
|
|
)
|
|
|
|
(defmethod new game-save ((allocation symbol) (type-to-make type) (arg0 int))
|
|
"Allocate a game save. arg0 is the number of bytes for tags."
|
|
(let ((v0-0 (object-new allocation type-to-make (the-as int (+ (-> type-to-make size) (the-as uint arg0))))))
|
|
(set! (-> v0-0 version) SAVE_VERSION)
|
|
(set! (-> v0-0 allocated-length) arg0)
|
|
v0-0
|
|
)
|
|
)
|
|
|
|
(defun-debug game-save-elt->string ((arg0 game-save-elt))
|
|
(enum->string game-save-elt arg0)
|
|
)
|
|
|
|
(defun progress-level-index->string ((arg0 int))
|
|
"Convert an index for a level in the progress menu (not actual data levels)
|
|
to a string (translated)."
|
|
(if (< arg0 (-> *level-task-data* length))
|
|
(lookup-text! *common-text* (-> *level-task-data* arg0 level-name-id) #f)
|
|
(the-as string #f)
|
|
)
|
|
)
|
|
|
|
(defmethod debug-print game-save ((obj game-save) (detail symbol))
|
|
"Print a save to #t"
|
|
(format #t "[~8x] ~A~%" obj (-> obj type))
|
|
(format #t "~Tversion: ~D~%" (-> obj version))
|
|
(format #t "~Tallocated-length: ~D~%" (-> obj allocated-length))
|
|
(format #t "~Tlength: ~D~%" (-> obj length))
|
|
(format #t "~Tlevel-index: ~D~%" (-> obj level-index))
|
|
(format #t "~Tfuel-cell-count: ~f~%" (-> obj fuel-cell-count))
|
|
(format #t "~Tmoney-count: ~f~%" (-> obj money-count))
|
|
(format #t "~Tbuzzer-count: ~f~%" (-> obj buzzer-count))
|
|
(format #t "~Tcompletion-percentage: ~f~%" (-> obj completion-percentage))
|
|
(format #t "~Tsave-time: ~x:~x ~x/~x/~x~%"
|
|
(-> obj hour)
|
|
(-> obj minute)
|
|
(-> obj day)
|
|
(-> obj month)
|
|
(-> obj year)
|
|
)
|
|
(format #t "~Ttag[]: @ #x~X~%" (-> obj tag))
|
|
|
|
;; loop through tags
|
|
(let ((tag (the-as game-save-tag (-> obj tag)))
|
|
(tag-idx 0)
|
|
)
|
|
(while (< (the-as int tag) (the-as int (-> obj tag (-> obj length))))
|
|
(format #t "~T [~3D] ~-32S [~3D/~3D] ~12D ~8f "
|
|
tag-idx
|
|
(game-save-elt->string (-> tag elt-type))
|
|
(-> tag elt-count)
|
|
(-> tag elt-size)
|
|
(-> tag user-uint64)
|
|
(-> tag user-float))
|
|
|
|
;; name/continue are strings
|
|
(let ((v1-0 (-> tag elt-type)))
|
|
(if (or (= v1-0 (game-save-elt name)) (= v1-0 (game-save-elt continue)))
|
|
(format #t "= \"~G\"~%" (&+ (the-as pointer tag) 16))
|
|
(format #t "~%")
|
|
)
|
|
)
|
|
|
|
(when detail
|
|
(let ((v1-4 (-> tag elt-type)))
|
|
(cond
|
|
((or (= v1-4 (game-save-elt moeny-per-level)) (= v1-4 (game-save-elt deaths-per-level)))
|
|
;; per level u8's
|
|
(dotimes (prog-lev-idx (-> tag elt-count))
|
|
(let ((lev-name (progress-level-index->string prog-lev-idx)))
|
|
(if lev-name
|
|
(format #t " ~-32S: ~D~%"
|
|
lev-name
|
|
(-> (the-as (pointer uint8) (&+ (the-as pointer (&-> (the-as (pointer uint8) tag) 16)) prog-lev-idx)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-4 (game-save-elt enter-level-time))
|
|
;; per level u64's
|
|
(dotimes (s2-2 (-> tag elt-count))
|
|
(let ((a2-14 (progress-level-index->string s2-2)))
|
|
(if a2-14
|
|
(format #t " ~-32S: ~D~%"
|
|
a2-14
|
|
(-> (the-as (pointer uint64) (&+ (&+ (the-as pointer tag) 16) (* s2-2 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-4 (game-save-elt in-level-time))
|
|
(dotimes (s2-3 (-> tag elt-count))
|
|
(let ((a2-15 (progress-level-index->string s2-3)))
|
|
(if a2-15
|
|
(format #t " ~-32S: ~D~%"
|
|
a2-15
|
|
(-> (the-as (pointer uint64) (&+ (&+ (the-as pointer tag) 16) (* s2-3 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-4 (game-save-elt fuel-cell-time))
|
|
(dotimes (s2-4 (-> tag elt-count))
|
|
(let ((a2-16 (game-task->string (the game-task s2-4))))
|
|
(if a2-16
|
|
(format #t " ~-32S: ~D~%"
|
|
a2-16
|
|
(-> (the-as (pointer uint64) (&+ (&+ (the-as pointer tag) 16) (* s2-4 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! tag (the-as game-save-tag
|
|
(&+ (the-as pointer tag)
|
|
(logand -16 (+ (* (the-as int (-> tag elt-size)) (-> tag elt-count)) 31))
|
|
)
|
|
)
|
|
)
|
|
(+! tag-idx 1)
|
|
)
|
|
)
|
|
obj
|
|
)
|
|
|
|
(defmethod inspect game-save ((obj game-save))
|
|
(debug-print obj #f)
|
|
)
|
|
|
|
(defmethod save-game! game-info ((obj game-info) (arg0 game-save) (arg1 string))
|
|
"Update the game-save to have the info from the current game state"
|
|
|
|
;; some stuff lives in the levels and needs to be copied into game-info.
|
|
(dotimes (s3-0 (-> *level* length))
|
|
(let ((a1-1 (-> *level* level s3-0)))
|
|
(if (= (-> a1-1 status) 'active)
|
|
(copy-perms-from-level! obj a1-1)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; set common data
|
|
(set! (-> arg0 length) 0)
|
|
(set! (-> arg0 version) 1)
|
|
(set!
|
|
(-> arg0 level-index)
|
|
(-> (lookup-level-info (-> obj current-continue level)) index)
|
|
)
|
|
(set! (-> arg0 fuel-cell-count) (-> obj fuel))
|
|
(set! (-> arg0 money-count) (-> obj money-total))
|
|
(set! (-> arg0 buzzer-count) (-> obj buzzer-total))
|
|
(set! (-> arg0 completion-percentage) (calculate-completion (the-as progress #f)))
|
|
(when (string= (-> obj current-continue name) "title-start")
|
|
(set! (-> arg0 new-game) 1)
|
|
(set! (-> arg0 level-index) (-> (lookup-level-info 'training) index))
|
|
(set! (-> arg0 fuel-cell-count) 0.0)
|
|
(set! (-> arg0 money-count) 0.0)
|
|
(set! (-> arg0 buzzer-count) 0.0)
|
|
(set! (-> arg0 completion-percentage) 0.0)
|
|
)
|
|
(let ((s3-1 (new 'stack 'scf-time)))
|
|
(scf-get-time s3-1)
|
|
(when (zero? (-> s3-1 stat))
|
|
(set! (-> arg0 minute) (-> s3-1 minute))
|
|
(set! (-> arg0 hour) (-> s3-1 hour))
|
|
(set! (-> arg0 day) (-> s3-1 day))
|
|
(set! (-> arg0 week) (-> s3-1 week))
|
|
(set! (-> arg0 month) (-> s3-1 month))
|
|
(set! (-> arg0 year) (-> s3-1 year))
|
|
)
|
|
)
|
|
|
|
;; set tags.
|
|
(let ((s3-2 (the-as object (-> arg0 tag))))
|
|
(let ((s2-0 (-> (the-as (inline-array game-save-tag) s3-2) 0)))
|
|
(set! (-> s2-0 elt-type) (game-save-elt name))
|
|
(set! (-> s2-0 elt-count) (+ (length arg1) 1))
|
|
(set! (-> s2-0 elt-size) (the-as uint 1))
|
|
)
|
|
(copy-charp<-charp
|
|
(the-as (pointer uint8) (-> (the-as (inline-array game-save-tag) s3-2) 1))
|
|
(-> arg1 data)
|
|
)
|
|
(let
|
|
((v1-37
|
|
(&+
|
|
(the-as pointer s3-2)
|
|
(+
|
|
(logand
|
|
-16
|
|
(+ (-> (the-as (inline-array game-save-tag) s3-2) 0 elt-count) 15)
|
|
)
|
|
16
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((a0-15 (the-as game-save-tag (&+ v1-37 0))))
|
|
(set! (-> a0-15 elt-type) (game-save-elt base-time))
|
|
(set! (-> a0-15 elt-count) 0)
|
|
(set!
|
|
(-> a0-15 user-uint64)
|
|
(the-as uint (-> *display* base-frame-counter))
|
|
)
|
|
)
|
|
(let ((v1-38 (&+ v1-37 16)))
|
|
(let ((a0-16 (the-as game-save-tag (&+ v1-38 0))))
|
|
(set! (-> a0-16 elt-type) (game-save-elt real-time))
|
|
(set! (-> a0-16 elt-count) 0)
|
|
(set!
|
|
(-> a0-16 user-uint64)
|
|
(the-as uint (-> *display* real-frame-counter))
|
|
)
|
|
)
|
|
(let ((v1-39 (&+ v1-38 16)))
|
|
(let ((a0-17 (the-as game-save-tag (&+ v1-39 0))))
|
|
(set! (-> a0-17 elt-type) (game-save-elt game-time))
|
|
(set! (-> a0-17 elt-count) 0)
|
|
(set!
|
|
(-> a0-17 user-uint64)
|
|
(the-as uint (-> *display* game-frame-counter))
|
|
)
|
|
)
|
|
(let ((v1-40 (&+ v1-39 16)))
|
|
(let ((a0-18 (the-as game-save-tag (&+ v1-40 0))))
|
|
(set! (-> a0-18 elt-type) (game-save-elt integral-time))
|
|
(set! (-> a0-18 elt-count) 0)
|
|
(set!
|
|
(-> a0-18 user-uint64)
|
|
(the-as uint (-> *display* integral-frame-counter))
|
|
)
|
|
)
|
|
(let ((s4-1 (the-as object (&+ v1-40 16))))
|
|
(let ((s3-3 (-> obj current-continue name)))
|
|
(let
|
|
((s2-1
|
|
(the-as game-save-tag (-> (the-as game-save-tag s4-1) user-object))
|
|
)
|
|
)
|
|
(set! (-> s2-1 elt-type) (game-save-elt continue))
|
|
(set! (-> s2-1 elt-count) (+ (length s3-3) 1))
|
|
(set! (-> s2-1 elt-size) (the-as uint 1))
|
|
)
|
|
(copy-charp<-charp
|
|
(the-as
|
|
(pointer uint8)
|
|
(the-as game-save-tag (&+ (the-as game-save-tag s4-1) 16))
|
|
)
|
|
(-> s3-3 data)
|
|
)
|
|
)
|
|
(let
|
|
((v1-50
|
|
(&+
|
|
(the-as pointer s4-1)
|
|
(+
|
|
(logand -16 (+ (-> (the-as game-save-tag s4-1) elt-count) 15))
|
|
16
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((a0-24 (the-as game-save-tag (&+ v1-50 0))))
|
|
(set! (-> a0-24 elt-type) (game-save-elt life))
|
|
(set! (-> a0-24 elt-count) 0)
|
|
(set! (-> a0-24 user-float0) (-> obj life))
|
|
)
|
|
(let ((v1-51 (&+ v1-50 16)))
|
|
(let ((a0-25 (the-as game-save-tag (&+ v1-51 0))))
|
|
(set! (-> a0-25 elt-type) (game-save-elt buzzer-total))
|
|
(set! (-> a0-25 elt-count) 0)
|
|
(set! (-> a0-25 user-float0) (-> obj buzzer-total))
|
|
)
|
|
(let ((v1-52 (&+ v1-51 16)))
|
|
(let ((a0-26 (the-as game-save-tag (&+ v1-52 0))))
|
|
(set! (-> a0-26 elt-type) (game-save-elt fuel-cell))
|
|
(set! (-> a0-26 elt-count) 0)
|
|
(set! (-> a0-26 user-float0) (-> obj fuel))
|
|
)
|
|
(let ((v1-53 (&+ v1-52 16)))
|
|
(let ((a0-27 (the-as game-save-tag (&+ v1-53 0))))
|
|
(set! (-> a0-27 elt-type) (game-save-elt death-movie-tick))
|
|
(set! (-> a0-27 elt-count) 0)
|
|
(set!
|
|
(-> a0-27 user-uint64)
|
|
(the-as uint (-> obj death-movie-tick))
|
|
)
|
|
)
|
|
(let ((v1-54 (&+ v1-53 16)))
|
|
(let ((a0-28 (the-as game-save-tag (&+ v1-54 0))))
|
|
(set! (-> a0-28 elt-type) (game-save-elt money))
|
|
(set! (-> a0-28 elt-count) 0)
|
|
(set! (-> a0-28 user-float0) (-> obj money))
|
|
)
|
|
(let ((v1-55 (&+ v1-54 16)))
|
|
(let ((a0-29 (the-as game-save-tag (&+ v1-55 0))))
|
|
(set! (-> a0-29 elt-type) (game-save-elt money-total))
|
|
(set! (-> a0-29 elt-count) 0)
|
|
(set! (-> a0-29 user-float0) (-> obj money-total))
|
|
)
|
|
(let ((v1-56 (&+ v1-55 16)))
|
|
(let ((a0-30 (the-as game-save-tag (&+ v1-56 0))))
|
|
(set! (-> a0-30 elt-type) (game-save-elt moeny-per-level))
|
|
(set! (-> a0-30 elt-count) 32)
|
|
(set! (-> a0-30 elt-size) (the-as uint 1))
|
|
)
|
|
(let ((v1-57 (&+ v1-56 16)))
|
|
(dotimes (a0-31 32)
|
|
(set!
|
|
(-> (the-as (pointer uint8) (&+ v1-57 a0-31)))
|
|
(-> obj money-per-level a0-31)
|
|
)
|
|
)
|
|
(let ((v1-58 (&+ v1-57 32)))
|
|
(let ((a0-34 (the-as object (&+ v1-58 0))))
|
|
(set!
|
|
(-> (the-as game-save-tag a0-34) elt-type)
|
|
(game-save-elt level-open-list)
|
|
)
|
|
(set! (-> (the-as game-save-tag a0-34) elt-count) 32)
|
|
(set!
|
|
(-> (the-as game-save-tag a0-34) elt-size)
|
|
(the-as uint 1)
|
|
)
|
|
)
|
|
(let ((v1-59 (&+ v1-58 16)))
|
|
(dotimes (a0-35 32)
|
|
(set!
|
|
(-> (the-as (pointer uint8) (&+ v1-59 a0-35)))
|
|
(-> obj level-opened a0-35)
|
|
)
|
|
)
|
|
(let ((v1-60 (&+ v1-59 32))
|
|
(s4-2
|
|
(-> (the-as (pointer int32) (-> obj perm-list)) 0)
|
|
)
|
|
)
|
|
(let ((a0-39 (the-as game-save-tag (&+ v1-60 0))))
|
|
(set! (-> a0-39 elt-type) (game-save-elt perm-list))
|
|
(set! (-> a0-39 elt-count) s4-2)
|
|
(set! (-> a0-39 elt-size) (the-as uint 16))
|
|
)
|
|
(let ((s3-4 (&+ v1-60 16)))
|
|
(dotimes (s2-2 s4-2)
|
|
(mem-copy!
|
|
(the-as
|
|
pointer
|
|
(the-as game-save-tag (&+ s3-4 (* s2-2 16)))
|
|
)
|
|
(the-as pointer (-> obj perm-list data s2-2))
|
|
16
|
|
)
|
|
)
|
|
(let ((v1-68 (&+ s3-4 (logand -16 (+ (* s4-2 16) 15))))
|
|
(s4-3 (-> obj task-perm-list length))
|
|
)
|
|
(let ((a0-45 (the-as game-save-tag (&+ v1-68 0))))
|
|
(set! (-> a0-45 elt-type) (game-save-elt task-list))
|
|
(set! (-> a0-45 elt-count) s4-3)
|
|
(set! (-> a0-45 elt-size) (the-as uint 16))
|
|
)
|
|
(let ((s3-5 (&+ v1-68 16)))
|
|
(dotimes (s2-3 s4-3)
|
|
(mem-copy!
|
|
(the-as
|
|
pointer
|
|
(the-as game-save-tag (&+ s3-5 (* s2-3 16)))
|
|
)
|
|
(the-as pointer (-> obj task-perm-list data s2-3))
|
|
16
|
|
)
|
|
)
|
|
(let ((a0-49 (&+ s3-5 (logand -16 (+ (* s4-3 16) 15))))
|
|
(v1-79
|
|
(/
|
|
(logand
|
|
-8
|
|
(+ (-> obj text-ids-seen allocated-length) 7)
|
|
)
|
|
8
|
|
)
|
|
)
|
|
)
|
|
(let ((a1-46 (the-as object (&+ a0-49 0))))
|
|
(set!
|
|
(-> (the-as game-save-tag a1-46) elt-type)
|
|
(game-save-elt text-list)
|
|
)
|
|
(set! (-> (the-as game-save-tag a1-46) elt-count) v1-79)
|
|
(set!
|
|
(-> (the-as game-save-tag a1-46) elt-size)
|
|
(the-as uint 1)
|
|
)
|
|
)
|
|
(let ((a0-50 (&+ a0-49 16)))
|
|
(dotimes (a1-47 v1-79)
|
|
(set!
|
|
(-> (the-as (pointer uint8) (&+ a0-50 a1-47)))
|
|
(-> obj text-ids-seen bytes a1-47)
|
|
)
|
|
)
|
|
(let ((a0-51 (&+ a0-50 (logand -16 (+ v1-79 15))))
|
|
(v1-84 (-> obj hint-control length))
|
|
)
|
|
(let ((a1-51 (the-as game-save-tag (&+ a0-51 0))))
|
|
(set! (-> a1-51 elt-type) (game-save-elt hint-list))
|
|
(set! (-> a1-51 elt-count) v1-84)
|
|
(set! (-> a1-51 elt-size) (the-as uint 32))
|
|
)
|
|
(let ((a0-52 (&+ a0-51 16)))
|
|
(dotimes (a1-52 v1-84)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer int64)
|
|
(&+ a0-52 (* (* a1-52 4) 8))
|
|
)
|
|
)
|
|
(-> obj hint-control a1-52 start-time)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer int64)
|
|
(&+ a0-52 (* (+ (* a1-52 4) 1) 8))
|
|
)
|
|
)
|
|
(-> obj hint-control a1-52 last-time-called)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer int8)
|
|
(&+ a0-52 (+ (* a1-52 32) 16))
|
|
)
|
|
)
|
|
(-> obj hint-control a1-52 num-attempts)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer int8)
|
|
(&+ a0-52 (+ (* a1-52 32) 17))
|
|
)
|
|
)
|
|
(-> obj hint-control a1-52 num-success)
|
|
)
|
|
)
|
|
(let ((v1-86 (&+ a0-52 (* v1-84 32))))
|
|
(let ((a0-54 (the-as game-save-tag (&+ v1-86 0))))
|
|
(set!
|
|
(-> a0-54 elt-type)
|
|
(game-save-elt auto-save-count)
|
|
)
|
|
(set! (-> a0-54 elt-count) 0)
|
|
(set!
|
|
(-> a0-54 user-uint64)
|
|
(the-as uint (-> obj auto-save-count))
|
|
)
|
|
)
|
|
(let ((v1-87 (&+ v1-86 16)))
|
|
(let ((a0-55 (the-as game-save-tag (&+ v1-87 0))))
|
|
(set!
|
|
(-> a0-55 elt-type)
|
|
(game-save-elt total-deaths)
|
|
)
|
|
(set! (-> a0-55 elt-count) 0)
|
|
(set!
|
|
(-> a0-55 user-uint64)
|
|
(the-as uint (-> obj total-deaths))
|
|
)
|
|
)
|
|
(let ((v1-88 (&+ v1-87 16)))
|
|
(let ((a0-56 (the-as game-save-tag (&+ v1-88 0))))
|
|
(set!
|
|
(-> a0-56 elt-type)
|
|
(game-save-elt continue-deaths)
|
|
)
|
|
(set! (-> a0-56 elt-count) 0)
|
|
(set!
|
|
(-> a0-56 user-uint64)
|
|
(the-as uint (-> obj continue-deaths))
|
|
)
|
|
)
|
|
(let ((v1-89 (&+ v1-88 16)))
|
|
(let ((a0-57 (the-as game-save-tag (&+ v1-89 0))))
|
|
(set!
|
|
(-> a0-57 elt-type)
|
|
(game-save-elt fuel-cell-deaths)
|
|
)
|
|
(set! (-> a0-57 elt-count) 0)
|
|
(set!
|
|
(-> a0-57 user-uint64)
|
|
(the-as uint (-> obj fuel-cell-deaths))
|
|
)
|
|
)
|
|
(let ((v1-90 (&+ v1-89 16)))
|
|
(let
|
|
((a0-58 (the-as game-save-tag (&+ v1-90 0))))
|
|
(set!
|
|
(-> a0-58 elt-type)
|
|
(game-save-elt game-start-time)
|
|
)
|
|
(set! (-> a0-58 elt-count) 0)
|
|
(set!
|
|
(-> a0-58 user-uint64)
|
|
(-> obj game-start-time)
|
|
)
|
|
)
|
|
(let ((v1-91 (&+ v1-90 16)))
|
|
(let
|
|
((a0-59 (the-as game-save-tag (&+ v1-91 0))))
|
|
(set!
|
|
(-> a0-59 elt-type)
|
|
(game-save-elt continue-time)
|
|
)
|
|
(set! (-> a0-59 elt-count) 0)
|
|
(set!
|
|
(-> a0-59 user-uint64)
|
|
(-> obj continue-time)
|
|
)
|
|
)
|
|
(let ((v1-92 (&+ v1-91 16)))
|
|
(let
|
|
((a0-60 (the-as game-save-tag (&+ v1-92 0))))
|
|
(set!
|
|
(-> a0-60 elt-type)
|
|
(game-save-elt death-time)
|
|
)
|
|
(set! (-> a0-60 elt-count) 0)
|
|
(set!
|
|
(-> a0-60 user-uint64)
|
|
(-> obj death-time)
|
|
)
|
|
)
|
|
(let ((v1-93 (&+ v1-92 16)))
|
|
(let
|
|
((a0-61 (the-as game-save-tag (&+ v1-93 0))))
|
|
(set!
|
|
(-> a0-61 elt-type)
|
|
(game-save-elt hit-time)
|
|
)
|
|
(set! (-> a0-61 elt-count) 0)
|
|
(set!
|
|
(-> a0-61 user-uint64)
|
|
(-> obj hit-time)
|
|
)
|
|
)
|
|
(let ((v1-94 (&+ v1-93 16)))
|
|
(let
|
|
((a0-62 (the-as game-save-tag (&+ v1-94 0)))
|
|
)
|
|
(set!
|
|
(-> a0-62 elt-type)
|
|
(game-save-elt fuel-cell-pickup-time)
|
|
)
|
|
(set! (-> a0-62 elt-count) 0)
|
|
(set!
|
|
(-> a0-62 user-uint64)
|
|
(-> obj fuel-cell-pickup-time)
|
|
)
|
|
)
|
|
(let ((v1-95 (&+ v1-94 16)))
|
|
(let
|
|
((a0-63
|
|
(the-as game-save-tag (&+ v1-95 0))
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-63 elt-type)
|
|
(game-save-elt fuel-cell-time)
|
|
)
|
|
(set! (-> a0-63 elt-count) 116)
|
|
(set! (-> a0-63 elt-size) (the-as uint 8))
|
|
)
|
|
(let ((v1-96 (&+ v1-95 16)))
|
|
(let ((a0-64 (the-as object 0)))
|
|
(while (< (the-as int a0-64) 116)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer uint64)
|
|
(&+ v1-96 (* (the-as int a0-64) 8))
|
|
)
|
|
)
|
|
(->
|
|
obj
|
|
fuel-cell-time
|
|
(the-as int a0-64)
|
|
)
|
|
)
|
|
(set! a0-64 (+ (the-as int a0-64) 1))
|
|
)
|
|
)
|
|
(let ((v1-97 (&+ v1-96 928)))
|
|
(let
|
|
((a0-67
|
|
(the-as game-save-tag (&+ v1-97 0))
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-67 elt-type)
|
|
(game-save-elt deaths-per-level)
|
|
)
|
|
(set! (-> a0-67 elt-count) 32)
|
|
(set!
|
|
(-> a0-67 elt-size)
|
|
(the-as uint 1)
|
|
)
|
|
)
|
|
(let ((v1-98 (&+ v1-97 16)))
|
|
(dotimes (a0-68 32)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer uint8)
|
|
(&+ v1-98 a0-68)
|
|
)
|
|
)
|
|
(-> obj deaths-per-level a0-68)
|
|
)
|
|
)
|
|
(let ((v1-99 (&+ v1-98 32)))
|
|
(let
|
|
((a0-71
|
|
(the-as game-save-tag (&+ v1-99 0))
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-71 elt-type)
|
|
(game-save-elt enter-level-time)
|
|
)
|
|
(set! (-> a0-71 elt-count) 32)
|
|
(set!
|
|
(-> a0-71 elt-size)
|
|
(the-as uint 8)
|
|
)
|
|
)
|
|
(let ((v1-100 (&+ v1-99 16)))
|
|
(dotimes (a0-72 32)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer uint64)
|
|
(&+ v1-100 (* a0-72 8))
|
|
)
|
|
)
|
|
(-> obj enter-level-time a0-72)
|
|
)
|
|
)
|
|
(let ((v1-101 (&+ v1-100 256)))
|
|
(let
|
|
((a0-75
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-101 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-75 elt-type)
|
|
(game-save-elt in-level-time)
|
|
)
|
|
(set! (-> a0-75 elt-count) 32)
|
|
(set!
|
|
(-> a0-75 elt-size)
|
|
(the-as uint 8)
|
|
)
|
|
)
|
|
(let ((v1-102 (&+ v1-101 16)))
|
|
(dotimes (a0-76 32)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer uint64)
|
|
(&+ v1-102 (* a0-76 8))
|
|
)
|
|
)
|
|
(-> obj in-level-time a0-76)
|
|
)
|
|
)
|
|
(let ((v1-103 (&+ v1-102 256)))
|
|
(let
|
|
((a0-79
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-103 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-79 elt-type)
|
|
(game-save-elt sfx-volume)
|
|
)
|
|
(set! (-> a0-79 elt-count) 0)
|
|
(set!
|
|
(-> a0-79 user-float0)
|
|
(->
|
|
*setting-control*
|
|
default
|
|
sfx-volume
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-104 (&+ v1-103 16)))
|
|
(let
|
|
((a0-80
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-104 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-80 elt-type)
|
|
(game-save-elt music-volume)
|
|
)
|
|
(set! (-> a0-80 elt-count) 0)
|
|
(set!
|
|
(-> a0-80 user-float0)
|
|
(->
|
|
*setting-control*
|
|
default
|
|
music-volume
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-105 (&+ v1-104 16)))
|
|
(let
|
|
((a0-81
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-105 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-81 elt-type)
|
|
(game-save-elt dialog-volume)
|
|
)
|
|
(set! (-> a0-81 elt-count) 0)
|
|
(set!
|
|
(-> a0-81 user-float0)
|
|
(->
|
|
*setting-control*
|
|
default
|
|
dialog-volume
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-106 (&+ v1-105 16)))
|
|
(let
|
|
((a0-82
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-106 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-82 elt-type)
|
|
(game-save-elt language)
|
|
)
|
|
(set! (-> a0-82 elt-count) 0)
|
|
(set!
|
|
(-> a0-82 user-uint64)
|
|
(the-as
|
|
uint
|
|
(->
|
|
*setting-control*
|
|
default
|
|
language
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-107 (&+ v1-106 16)))
|
|
(let
|
|
((a0-83
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-107 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-83 elt-type)
|
|
(game-save-elt screenx)
|
|
)
|
|
(set! (-> a0-83 elt-count) 0)
|
|
(set!
|
|
(-> a0-83 user-float0)
|
|
(the
|
|
float
|
|
(->
|
|
*setting-control*
|
|
default
|
|
screenx
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-108 (&+ v1-107 16)))
|
|
(let
|
|
((a0-84
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-108 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-84 elt-type)
|
|
(game-save-elt screeny)
|
|
)
|
|
(set! (-> a0-84 elt-count) 0)
|
|
(set!
|
|
(-> a0-84 user-float0)
|
|
(the
|
|
float
|
|
(->
|
|
*setting-control*
|
|
default
|
|
screeny
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-109 (&+ v1-108 16)))
|
|
(let
|
|
((a0-85
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-109 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-85 elt-type)
|
|
(game-save-elt vibration)
|
|
)
|
|
(set! (-> a0-85 elt-count) 0)
|
|
(set!
|
|
(-> a0-85 user-uint64)
|
|
(the-as
|
|
uint
|
|
(if
|
|
(->
|
|
*setting-control*
|
|
default
|
|
vibration
|
|
)
|
|
1
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((v1-110 (&+ v1-109 16)))
|
|
(let
|
|
((a0-86
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-110 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-86 elt-type)
|
|
(game-save-elt play-hints)
|
|
)
|
|
(set!
|
|
(-> a0-86 elt-count)
|
|
0
|
|
)
|
|
(set!
|
|
(-> a0-86 user-uint64)
|
|
(the-as
|
|
uint
|
|
(if
|
|
(->
|
|
*setting-control*
|
|
default
|
|
play-hints
|
|
)
|
|
1
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let
|
|
((v1-111 (&+ v1-110 16)))
|
|
(let
|
|
((a0-87
|
|
(the-as
|
|
game-save-tag
|
|
(&+ v1-111 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-87 elt-type)
|
|
(game-save-elt video-mode)
|
|
)
|
|
(set!
|
|
(-> a0-87 elt-count)
|
|
0
|
|
)
|
|
(let
|
|
((a1-121
|
|
(->
|
|
*setting-control*
|
|
default
|
|
video-mode
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> a0-87 user-uint64)
|
|
(the-as uint (cond
|
|
((=
|
|
a1-121
|
|
'ntsc
|
|
)
|
|
1
|
|
)
|
|
((=
|
|
a1-121
|
|
'pal
|
|
)
|
|
2
|
|
)
|
|
(else
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let
|
|
((v1-112 (&+ v1-111 16)))
|
|
(let
|
|
((a0-88
|
|
(the-as
|
|
object
|
|
(&+ v1-112 0)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
game-save-tag
|
|
a0-88
|
|
)
|
|
elt-type
|
|
)
|
|
(game-save-elt
|
|
aspect-ratio
|
|
)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
game-save-tag
|
|
a0-88
|
|
)
|
|
elt-count
|
|
)
|
|
0
|
|
)
|
|
(let
|
|
((a1-125
|
|
(->
|
|
*setting-control*
|
|
default
|
|
aspect-ratio
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(->
|
|
(the-as
|
|
(pointer int64)
|
|
a0-88
|
|
)
|
|
)
|
|
(cond
|
|
((= a1-125 'aspect4x3)
|
|
1
|
|
)
|
|
((= a1-125 'aspect16x9)
|
|
2
|
|
)
|
|
(else
|
|
0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> arg0 length)
|
|
(&-
|
|
(&+ v1-112 16)
|
|
(the-as
|
|
uint
|
|
(the-as
|
|
pointer
|
|
(-> arg0 tag)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(if (< (-> arg0 allocated-length) (-> arg0 length))
|
|
(format
|
|
0
|
|
"ERROR: SAVEGAME: fatal error, save is using ~D of ~D bytes."
|
|
(-> arg0 length)
|
|
(-> arg0 allocated-length)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defmethod load-game! game-info ((obj game-info) (save game-save))
|
|
"Copy save data from a game-save to a game-info"
|
|
(let ((save-data (the-as game-save-tag (-> save tag))))
|
|
;; loop over all tags
|
|
(while (< (the-as int save-data) (the-as int (+ (+ (-> save length) 76) (the-as int save))))
|
|
(let ((a0-1 (-> save-data elt-type)))
|
|
(cond
|
|
((= a0-1 (game-save-elt sfx-volume))
|
|
(set! (-> *setting-control* default sfx-volume) (-> save-data user-float0))
|
|
)
|
|
((= a0-1 (game-save-elt music-volume))
|
|
(set! (-> *setting-control* default music-volume) (-> save-data user-float0))
|
|
)
|
|
((= a0-1 (game-save-elt dialog-volume))
|
|
(set! (-> *setting-control* default dialog-volume) (-> save-data user-float0))
|
|
)
|
|
((= a0-1 (game-save-elt language))
|
|
(set! (-> *setting-control* default language) (the-as language-enum (-> save-data user-uint64)))
|
|
)
|
|
((= a0-1 (game-save-elt vibration))
|
|
(set! (-> *setting-control* default vibration) (= (-> save-data user-uint64) 1))
|
|
)
|
|
((= a0-1 (game-save-elt play-hints))
|
|
(set! (-> *setting-control* default play-hints) (= (-> save-data user-uint64) 1))
|
|
)
|
|
)
|
|
)
|
|
(set! save-data (the-as game-save-tag
|
|
(&+ (the-as pointer save-data)
|
|
(logand -16 (+ (* (the-as int (-> save-data elt-size)) (-> save-data elt-count)) 31))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; if we're a new game, set our checkpoint.
|
|
(when (nonzero? (-> save new-game))
|
|
(set-continue! obj "game-start")
|
|
(set! save save)
|
|
(goto cfg-134)
|
|
)
|
|
|
|
;; loop over all tags
|
|
(let ((data (the-as game-save-tag (-> save tag))))
|
|
(while (< (the-as int data) (the-as int (+ (+ (-> save length) 76) (the-as int save))))
|
|
(let ((v1-7 (-> data elt-type)))
|
|
(cond
|
|
((= v1-7 (game-save-elt base-time))
|
|
;; updating this requires some care to not break things
|
|
(let ((old-base-frame (-> *display* base-frame-counter)))
|
|
(set! (-> *display* base-frame-counter) (the int (-> data user-uint64)))
|
|
;; remember the old value
|
|
(set! (-> *display* old-base-frame-counter) (+ (-> *display* base-frame-counter) -1))
|
|
(let ((frame-counter-diff (- (-> *display* base-frame-counter) old-base-frame)))
|
|
|
|
;; update in-progress counters
|
|
(if (nonzero? (-> obj blackout-time))
|
|
(set! (-> obj blackout-time) (+ (-> obj blackout-time) frame-counter-diff))
|
|
)
|
|
(if (nonzero? (-> obj letterbox-time))
|
|
(set! (-> obj letterbox-time) (+ (-> obj letterbox-time) frame-counter-diff))
|
|
)
|
|
(if (nonzero? (-> obj hint-play-time))
|
|
(set! (-> obj hint-play-time) (+ (-> obj hint-play-time) frame-counter-diff))
|
|
)
|
|
(if (nonzero? (-> obj display-text-time))
|
|
(set! (-> obj display-text-time) (+ (-> obj display-text-time) frame-counter-diff))
|
|
)
|
|
)
|
|
)
|
|
;; vibration may get stuck on if we warp back in time, just kill it
|
|
(buzz-stop! 0)
|
|
)
|
|
|
|
((= v1-7 (game-save-elt game-time))
|
|
(set! (-> *display* game-frame-counter) (the int (-> data user-uint64)))
|
|
(set! (-> *display* old-game-frame-counter) (+ (-> *display* game-frame-counter) -1))
|
|
)
|
|
((= v1-7 (game-save-elt real-time))
|
|
(set! (-> *display* real-frame-counter) (the int (-> data user-uint64)))
|
|
(set! (-> *display* old-real-frame-counter) (+ (-> *display* real-frame-counter) -1))
|
|
)
|
|
((= v1-7 (game-save-elt integral-time))
|
|
(set! (-> *display* integral-frame-counter) (the int (-> data user-uint64)))
|
|
(set! (-> *display* old-integral-frame-counter) (+ (-> *display* integral-frame-counter) -1))
|
|
)
|
|
((= v1-7 (game-save-elt continue))
|
|
(format (clear *temp-string*) "~G" (&+ (the-as pointer data) 16))
|
|
(set-continue! obj *temp-string*)
|
|
)
|
|
((= v1-7 (game-save-elt life))
|
|
(set! (-> obj life) (-> data user-float0))
|
|
)
|
|
((= v1-7 (game-save-elt buzzer-total))
|
|
(set! (-> obj buzzer-total) (-> data user-float0))
|
|
)
|
|
((= v1-7 (game-save-elt fuel-cell))
|
|
(set! (-> obj fuel) (-> data user-float0))
|
|
)
|
|
((= v1-7 (game-save-elt death-movie-tick))
|
|
(set! (-> obj death-movie-tick) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt money))
|
|
(set! (-> obj money) (-> data user-float0))
|
|
)
|
|
((= v1-7 (game-save-elt money-total))
|
|
(set! (-> obj money-total) (-> data user-float0))
|
|
)
|
|
((= v1-7 (game-save-elt moeny-per-level))
|
|
(let ((v1-34 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-76 v1-34)
|
|
(set!
|
|
(-> obj money-per-level a0-76)
|
|
(-> (the-as (pointer uint8) (&+ (the-as pointer data) 16)) a0-76)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt level-open-list))
|
|
(let ((v1-38 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-80 v1-38)
|
|
(set!
|
|
(-> obj level-opened a0-80)
|
|
(-> (the-as (pointer uint8) (&+ (the-as pointer data) 16)) a0-80)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt perm-list))
|
|
(let ((s3-2 (min (-> data elt-count) (-> obj perm-list allocated-length))))
|
|
(set! (-> obj perm-list length) s3-2)
|
|
(dotimes (s2-0 s3-2)
|
|
(mem-copy!
|
|
(the-as pointer (-> obj perm-list data s2-0))
|
|
(&+ (&+ (the-as pointer data) 16) (* s2-0 16))
|
|
16
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt task-list))
|
|
(let ((s3-4 (min (-> data elt-count) (-> obj task-perm-list allocated-length))))
|
|
(set! (-> obj task-perm-list length) s3-4)
|
|
(dotimes (s2-1 s3-4)
|
|
(mem-copy!
|
|
(the-as pointer (-> obj task-perm-list data s2-1))
|
|
(&+ (&+ (the-as pointer data) 16) (* s2-1 16))
|
|
16
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt text-list))
|
|
(let ((v1-61 (/ (logand -8 (+ (-> obj text-ids-seen allocated-length) 7)) 8))
|
|
(a0-94 (-> data elt-count)))
|
|
(dotimes (a1-35 v1-61)
|
|
(cond
|
|
((>= a1-35 a0-94)
|
|
(set! (-> obj text-ids-seen bytes a1-35) (the-as uint 0))
|
|
0
|
|
)
|
|
(else
|
|
(set! (-> obj text-ids-seen bytes a1-35)
|
|
(-> (the-as (pointer uint8) (&+ (the-as pointer data) 16)) a1-35)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt hint-list))
|
|
(cond
|
|
((= (-> obj hint-control length) (-> data elt-count))
|
|
(let ((v1-65 (&+ (the-as pointer data) 16)))
|
|
(dotimes (a0-99 (-> data elt-count))
|
|
(set! (-> obj hint-control a0-99 start-time)
|
|
(-> (the-as (pointer int64) (&+ v1-65 (* (* a0-99 4) 8))))
|
|
)
|
|
(set! (-> obj hint-control a0-99 last-time-called)
|
|
(-> (the-as (pointer int64) (&+ v1-65 (* (+ (* a0-99 4) 1) 8))))
|
|
)
|
|
(set! (-> obj hint-control a0-99 num-attempts)
|
|
(-> (the-as (pointer int8)
|
|
(&+ (the-as (pointer uint8) v1-65) (+ (* a0-99 32) 16))
|
|
)
|
|
)
|
|
)
|
|
(set!
|
|
(-> obj hint-control a0-99 num-success)
|
|
(-> (the-as (pointer int8)
|
|
(&+ (the-as (pointer uint8) v1-65) (+ (* a0-99 32) 17))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(else
|
|
(format
|
|
0
|
|
"WARNING: SAVEGAME: hint control list did not match current, ignoring~%"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt auto-save-count))
|
|
(set! (-> obj auto-save-count) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt total-deaths))
|
|
(set! (-> obj total-deaths) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt continue-deaths))
|
|
(set! (-> obj continue-deaths) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt fuel-cell-deaths))
|
|
(set! (-> obj fuel-cell-deaths) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt game-start-time))
|
|
(set! (-> obj game-start-time) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt continue-time))
|
|
(set! (-> obj continue-time) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt death-time))
|
|
(set! (-> obj death-time) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt hit-time))
|
|
(set! (-> obj hit-time) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt fuel-cell-pickup-time))
|
|
(set! (-> obj fuel-cell-pickup-time) (the-as int (-> data user-uint64)))
|
|
)
|
|
((= v1-7 (game-save-elt deaths-per-level))
|
|
(let ((v1-79 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-122 v1-79)
|
|
(set!
|
|
(-> obj deaths-per-level a0-122)
|
|
(-> (the-as (pointer uint8) (&+ (the-as pointer data) 16)) a0-122)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt enter-level-time))
|
|
(let ((v1-83 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-126 v1-83)
|
|
(set! (-> obj enter-level-time a0-126)
|
|
(-> (the-as (pointer int64) (&+ (&+ (the-as pointer data) 16) (* a0-126 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt in-level-time))
|
|
(let ((v1-87 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-130 v1-87)
|
|
(set! (-> obj in-level-time a0-130)
|
|
(-> (the-as (pointer int64) (&+ (&+ (the-as pointer data) 16) (* a0-130 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= v1-7 (game-save-elt fuel-cell-time))
|
|
(let ((v1-92 (min 32 (-> data elt-count))))
|
|
(dotimes (a0-133 v1-92)
|
|
(set! (-> obj fuel-cell-time a0-133)
|
|
(-> (the-as (pointer int64) (&+ (&+ (the-as pointer data) 16) (* a0-133 8))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! data (the-as game-save-tag (&+ (the-as pointer data)
|
|
(logand -16
|
|
(+ (* (the-as int (-> data elt-size)) (-> data elt-count)) 31)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; update entity stuff in levels that are active
|
|
(dotimes (s4-1 (-> *level* length))
|
|
(let ((a1-68 (-> *level* level s4-1)))
|
|
(if (= (-> a1-68 status) 'active)
|
|
(copy-perms-to-level! obj a1-68)
|
|
)
|
|
)
|
|
)
|
|
;; update tasks
|
|
(let ((s5-1 2) ;; jungle eggtop
|
|
(s4-2 115) ;; max - 1
|
|
)
|
|
(while (>= (the-as uint s4-2) (the-as uint s5-1))
|
|
;; calling this will run the function to see if the task is done or not
|
|
(get-task-status (the-as game-task s5-1))
|
|
(+! s5-1 1)
|
|
)
|
|
)
|
|
(label cfg-134)
|
|
save
|
|
)
|
|
|
|
(defmethod save-to-file game-save ((obj game-save) (arg0 string))
|
|
"Write a game save to a file for debugging"
|
|
(let ((s5-0 (new 'stack 'file-stream arg0 'write)))
|
|
(file-stream-write s5-0
|
|
(&-> obj type)
|
|
(+ (-> obj type size) (the-as uint (-> obj length)))
|
|
)
|
|
(file-stream-close s5-0)
|
|
)
|
|
obj
|
|
)
|
|
|
|
(defmethod load-from-file! game-save ((obj game-save) (filename string))
|
|
"Load a game save from a file for debugging"
|
|
(let ((stream (new 'stack 'file-stream filename 'read)))
|
|
(let ((in-size (file-stream-length stream))
|
|
(my-size (-> obj allocated-length))
|
|
)
|
|
(cond
|
|
((>= (asize-of obj) in-size)
|
|
;; thing in file is not bigger than we are, safe to read.
|
|
(cond
|
|
((= (file-stream-read stream (&-> obj type) in-size) in-size)
|
|
;; read success! set the type tag
|
|
(set! (-> obj type) game-save)
|
|
)
|
|
(else
|
|
;; fail.
|
|
(format 0 "ERROR: SAVEGAME: save file ~A did not read correctly.~%" stream)
|
|
(set! (-> obj length) 0)
|
|
0
|
|
)
|
|
)
|
|
)
|
|
(else
|
|
;; file is bigger than we are, just give up because we don't have
|
|
;; enough room to put the save
|
|
(format 0 "ERROR: SAVEGAME: save file ~A is too big~%" stream)
|
|
)
|
|
)
|
|
(set! (-> obj allocated-length) my-size)
|
|
)
|
|
(when (!= (-> obj version) SAVE_VERSION)
|
|
;; uh-oh, the version is wrong
|
|
(format 0 "ERROR: SAVEGAME: save file ~A was version ~d, but only ~d is supported.~%"
|
|
stream
|
|
(-> obj version)
|
|
SAVE_VERSION
|
|
)
|
|
(set! (-> obj length) 0)
|
|
0
|
|
)
|
|
(file-stream-close stream)
|
|
)
|
|
obj
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; particles
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; used for the flashing auto-save icon, I think.
|
|
|
|
(set! (-> *part-group-id-table* 656)
|
|
(new 'static 'sparticle-launch-group
|
|
:length 1
|
|
:duration #xbb8
|
|
:linger-duration #x5dc
|
|
:flags (sp-group-flag screen-space)
|
|
:name "group-part-save-icon"
|
|
:launcher
|
|
(new 'static 'inline-array sparticle-group-item 1 (sp-item 2662))
|
|
:bounds (new 'static 'sphere :w 409600.0)
|
|
)
|
|
)
|
|
|
|
(set! (-> *part-id-table* 2662)
|
|
(new 'static 'sparticle-launcher
|
|
:init-specs
|
|
(new 'static 'inline-array sp-field-init-spec 11
|
|
(sp-tex spt-texture (new 'static 'texture-id :index #x6b :page #x1cf))
|
|
(sp-flt spt-num 1.0)
|
|
(sp-flt spt-scale-x (meters 1.5))
|
|
(sp-copy-from-other spt-scale-y -4)
|
|
(sp-flt spt-r 128.0)
|
|
(sp-flt spt-g 128.0)
|
|
(sp-flt spt-b 128.0)
|
|
(sp-flt spt-a 128.0)
|
|
(sp-int spt-timer 5)
|
|
(sp-cpuinfo-flags bit2 bit9 bit13)
|
|
(sp-end)
|
|
)
|
|
)
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; auto-save process
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; the status of the memory cards.
|
|
(define *auto-save-info* (new 'global 'mc-slot-info))
|
|
|
|
(deftype auto-save (process)
|
|
((card int32 :offset-assert 112)
|
|
(slot int32 :offset-assert 116)
|
|
(which int32 :offset-assert 120)
|
|
(buffer kheap :offset-assert 124)
|
|
(mode basic :offset-assert 128)
|
|
(result mc-status-code :offset-assert 132)
|
|
(save game-save :offset-assert 136)
|
|
(info mc-slot-info :inline :offset-assert 140)
|
|
(notify handle :offset-assert 440)
|
|
(state-time int64 :offset-assert 448)
|
|
(part sparticle-launch-control :offset-assert 456)
|
|
)
|
|
:heap-base #x160
|
|
:method-count-assert 23
|
|
:size-assert #x1cc
|
|
:flag-assert #x17016001cc
|
|
(:methods
|
|
(get-heap () _type_ :state 14)
|
|
(get-card () _type_ :state 15)
|
|
(format-card () _type_ :state 16)
|
|
(create-file () _type_ :state 17)
|
|
(save () _type_ :state 18)
|
|
(restore () _type_ :state 19)
|
|
(error (mc-status-code) _type_ :state 20)
|
|
(done () _type_ :state 21)
|
|
(unformat-card () _type_ :state 22)
|
|
)
|
|
)
|
|
|
|
(defmethod deactivate auto-save ((obj auto-save))
|
|
"Deactivate the auto-save process."
|
|
;; kill the particles
|
|
(if (nonzero? (-> obj part))
|
|
(kill-and-free-particles (-> obj part))
|
|
)
|
|
;; and do a normal deactivate.
|
|
((method-of-type process deactivate) obj)
|
|
(none)
|
|
)
|
|
|
|
(defmethod relocate auto-save ((obj auto-save) (arg0 int))
|
|
"Relocate an auto-save process by arg0 bytes."
|
|
|
|
;; update our reference particle launch control, which is allocated on our process heap
|
|
(if (nonzero? (-> obj part))
|
|
(&+! (-> obj part) arg0)
|
|
)
|
|
|
|
;; then relocate the process. This will relocate the heap (memory, and basics on it).
|
|
(the-as auto-save ((method-of-type process relocate) obj arg0))
|
|
)
|
|
|
|
(defbehavior auto-save-post auto-save ()
|
|
;; debug text
|
|
(when (and (= *cheat-mode* 'debug)
|
|
(logtest? (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons l3))
|
|
)
|
|
(let ((gp-0 (new 'stack 'font-context *font-default-matrix* 32 160 0.0 (font-color default) (font-flags shadow kerning))))
|
|
(let ((v1-5 gp-0))
|
|
(set! (-> v1-5 width) (the float 440))
|
|
)
|
|
(let ((v1-6 gp-0))
|
|
(set! (-> v1-6 height) (the float 80))
|
|
)
|
|
(set! (-> gp-0 flags) (font-flags shadow kerning))
|
|
(format (clear *temp-string*) "~S / ~S ~D~%"
|
|
(-> self mode)
|
|
(-> self state name)
|
|
(-> self which)
|
|
)
|
|
(print-game-text *temp-string* gp-0 #f 128 22)
|
|
)
|
|
)
|
|
|
|
;; auto-save drawing
|
|
(when (and (= (-> self mode) 'auto-save) (!= (-> self next-state name) 'done))
|
|
(let ((gp-1 (new 'stack 'font-context *font-default-matrix* 20 40 0.0 (font-color default) (font-flags shadow kerning))))
|
|
(let ((v1-15 gp-1))
|
|
(set! (-> v1-15 scale) 0.8)
|
|
)
|
|
(let ((v1-16 gp-1))
|
|
(set! (-> v1-16 width) (the float 472))
|
|
)
|
|
(let ((v1-17 gp-1))
|
|
(set! (-> v1-17 height) (the float 20))
|
|
)
|
|
(set! (-> gp-1 flags) (font-flags shadow kerning middle left large))
|
|
|
|
;; if this is the first time saving, display a warning.
|
|
(when (zero? (-> *game-info* auto-save-count))
|
|
(print-game-text (lookup-text! *common-text* (game-text-id saving-data) #f) gp-1 #f 128 22)
|
|
(set! (-> gp-1 origin x) 20.0)
|
|
(set! (-> gp-1 origin y) 130.0)
|
|
(let ((v1-23 gp-1))
|
|
(set! (-> v1-23 scale) 0.7)
|
|
)
|
|
(let ((v1-24 gp-1))
|
|
(set! (-> v1-24 height) (the float 40))
|
|
)
|
|
(let ((s5-2 print-game-text))
|
|
((the-as (function object string object none) format)
|
|
(clear *temp-string*)
|
|
(lookup-text! *common-text* (game-text-id do-not-remove-mem-card) #f)
|
|
1
|
|
)
|
|
(s5-2 *temp-string* gp-1 #f 128 22)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; flash the icon.
|
|
(when (< (mod (-> *display* real-frame-counter) 300) 270)
|
|
(if (> (-> self part matrix) 0)
|
|
(set-vector!
|
|
(sprite-get-user-hvdf (-> self part matrix))
|
|
1842.0
|
|
(the float (+ (the int (* 0.5 (- (* (if (= (get-aspect-ratio) 'aspect16x9)
|
|
370.0
|
|
360.0
|
|
)
|
|
(-> *video-parms* relative-y-scale)
|
|
)
|
|
(the float (-> *video-parms* screen-sy))
|
|
)
|
|
)
|
|
)
|
|
2048
|
|
)
|
|
)
|
|
(+ -1024.0 (-> *math-camera* hvdf-off z))
|
|
(-> *math-camera* hvdf-off w)
|
|
)
|
|
)
|
|
(spawn (-> self part) *zero-vector*)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defstatehandler auto-save :post auto-save-post)
|
|
|
|
|
|
|
|
(defbehavior auto-save-init-by-other auto-save ((desired-mode symbol) (notify-proc process-tree) (card-idx int) (file-idx int))
|
|
(format 0 "auto-save-init!~%")
|
|
;; trying to create multiple auto save procs, bad idea.
|
|
(when (handle->process (-> *game-info* auto-save-proc))
|
|
(send-event notify-proc 'notify 'error 16)
|
|
(return #f)
|
|
)
|
|
|
|
;; set us as the auto save proc
|
|
(set! (-> *game-info* auto-save-proc) (process->handle self))
|
|
(set! (-> *game-info* auto-save-status) (mc-status-code ok))
|
|
(stack-size-set! (-> self main-thread) 512)
|
|
(logclear! (-> self mask) (process-mask pause menu progress))
|
|
|
|
;; setup ourself
|
|
(set! (-> self card) card-idx)
|
|
(set! (-> self which) file-idx)
|
|
(set! (-> self buffer) #f)
|
|
(set! (-> self mode) desired-mode)
|
|
(set! (-> self result) (mc-status-code ok))
|
|
(set! (-> self save) #f)
|
|
(set! (-> self notify) (process->handle notify-proc))
|
|
(set! (-> self part) (create-launch-control (-> *part-group-id-table* 656) self))
|
|
(set! (-> self part matrix) (sprite-allocate-user-hvdf))
|
|
(cond
|
|
((= desired-mode 'auto-save)
|
|
(if (not (-> *setting-control* current auto-save))
|
|
(go-virtual error (mc-status-code no-auto-save))
|
|
)
|
|
(when (and (zero? (-> self card)) (-> *setting-control* current auto-save))
|
|
(set! (-> self card) (-> *game-info* auto-save-card))
|
|
(set! (-> self which) (-> *game-info* auto-save-which))
|
|
)
|
|
)
|
|
((= desired-mode 'error)
|
|
(set! (-> *setting-control* default auto-save) #f)
|
|
(go-virtual error (mc-status-code no-card))
|
|
)
|
|
)
|
|
(set! (-> *setting-control* default auto-save) #f)
|
|
(format 0 "going to get-heap!~%")
|
|
(go-virtual get-heap)
|
|
(none)
|
|
)
|
|
|
|
;; Get heap memory.
|
|
(defstate get-heap (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(set! (-> self state-time) (-> *display* real-frame-counter))
|
|
(let ((a0-1 (reserve-alloc *art-control*)))
|
|
(while (not a0-1)
|
|
(if (>= (- (-> *display* real-frame-counter) (-> self state-time)) #x4650)
|
|
(go-virtual error (mc-status-code no-memory))
|
|
)
|
|
(suspend)
|
|
(set! a0-1 (reserve-alloc *art-control*))
|
|
)
|
|
(set! (-> self buffer) a0-1)
|
|
)
|
|
(go-virtual get-card)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate get-card (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(label cfg-0)
|
|
(mc-get-slot-info (-> self slot) (-> self info))
|
|
(when (zero? (-> self info known))
|
|
(suspend)
|
|
(goto cfg-0)
|
|
)
|
|
(cond
|
|
((zero? (-> self info handle))
|
|
(go-virtual error (mc-status-code no-card))
|
|
)
|
|
((zero? (-> self card))
|
|
(set! (-> self card) (-> self info handle))
|
|
)
|
|
((!= (-> self info handle) (-> self card))
|
|
(go-virtual error (mc-status-code bad-handle))
|
|
)
|
|
)
|
|
(case (-> self mode)
|
|
(('save 'auto-save)
|
|
(go-virtual save)
|
|
)
|
|
(('save-last)
|
|
(set! (-> self which) (-> self info last-file))
|
|
(if (= (-> self which) -1)
|
|
(go-virtual error (mc-status-code no-last))
|
|
(go-virtual save)
|
|
)
|
|
)
|
|
(('restore)
|
|
(go-virtual restore)
|
|
)
|
|
(('format-card)
|
|
(go-virtual format-card)
|
|
)
|
|
(('unformat-card)
|
|
(go-virtual unformat-card)
|
|
)
|
|
(('create-file)
|
|
(go-virtual create-file)
|
|
)
|
|
(else
|
|
(go-virtual done)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate format-card (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(when (zero? (-> self info formatted))
|
|
(label cfg-1)
|
|
(set! (-> self result) (mc-format (-> self card)))
|
|
(when (!= (-> self result) (mc-status-code ok))
|
|
(suspend)
|
|
(goto cfg-1)
|
|
)
|
|
(label cfg-3)
|
|
(set! (-> self result) (the-as mc-status-code (mc-check-result)))
|
|
(let ((v1-4 (-> self result)))
|
|
(b! (nonzero? v1-4) cfg-5 :delay (nop!))
|
|
(b! #t cfg-10 :delay (nop!))
|
|
(label cfg-5)
|
|
(b! (= v1-4 (mc-status-code format-failed)) cfg-1 :delay (nop!))
|
|
(nop!)
|
|
(b! (!= v1-4 (mc-status-code ok)) cfg-9 :delay (nop!))
|
|
)
|
|
(b! #t cfg-12 :delay (nop!))
|
|
(the-as none 0)
|
|
(b! #t cfg-10 :delay (nop!))
|
|
(label cfg-9)
|
|
(go-virtual error (-> self result))
|
|
(label cfg-10)
|
|
(suspend)
|
|
(goto cfg-3)
|
|
;;(break ((empty)) ((empty-form)))
|
|
|
|
)
|
|
(label cfg-12)
|
|
(case (-> self mode)
|
|
(('create-file 'save 'save-last 'auto-save 'restore)
|
|
(go-virtual create-file)
|
|
)
|
|
)
|
|
(go-virtual done)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate unformat-card (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(when (nonzero? (-> self info formatted))
|
|
(label cfg-1)
|
|
(set! (-> self result) (mc-unformat (-> self card)))
|
|
(when (!= (-> self result) (mc-status-code ok))
|
|
(suspend)
|
|
(goto cfg-1)
|
|
)
|
|
(while #t
|
|
(set! (-> self result) (the-as mc-status-code (mc-check-result)))
|
|
(case (-> self result)
|
|
(((mc-status-code busy))
|
|
)
|
|
(((mc-status-code ok))
|
|
(goto cfg-11)
|
|
)
|
|
(else
|
|
(go-virtual error (-> self result))
|
|
)
|
|
)
|
|
(suspend)
|
|
)
|
|
)
|
|
(label cfg-11)
|
|
(go-virtual done)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate create-file (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(cond
|
|
((zero? (-> self info formatted))
|
|
(go-virtual error (mc-status-code no-format))
|
|
)
|
|
((zero? (-> self info inited))
|
|
(if (< (-> self info mem-actual) (-> self info mem-required))
|
|
(go-virtual error (mc-status-code no-space))
|
|
)
|
|
(let ((v1-12 (-> self buffer)))
|
|
(set! (-> v1-12 current) (-> v1-12 base))
|
|
)
|
|
(label cfg-6)
|
|
(set!
|
|
(-> self result)
|
|
(mc-create-file (-> self card) (the-as uint (-> self buffer base)))
|
|
)
|
|
(when (!= (-> self result) (mc-status-code ok))
|
|
(suspend)
|
|
(goto cfg-6)
|
|
)
|
|
(while #t
|
|
(set! (-> self result) (the-as mc-status-code (mc-check-result)))
|
|
(case (-> self result)
|
|
(((mc-status-code busy))
|
|
)
|
|
(((mc-status-code ok))
|
|
(goto cfg-16)
|
|
)
|
|
(else
|
|
(go-virtual error (-> self result))
|
|
)
|
|
)
|
|
(suspend)
|
|
)
|
|
)
|
|
)
|
|
(label cfg-16)
|
|
(case (-> self mode)
|
|
(('restore)
|
|
(go-virtual restore)
|
|
)
|
|
(('save 'save-last 'auto-save)
|
|
(go-virtual save)
|
|
)
|
|
)
|
|
(go-virtual done)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate save (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(cond
|
|
((zero? (-> self info formatted))
|
|
(go-virtual error (mc-status-code no-format))
|
|
)
|
|
((zero? (-> self info inited))
|
|
(go-virtual error (mc-status-code no-file))
|
|
)
|
|
)
|
|
(case (-> self mode)
|
|
(('auto-save)
|
|
(+! (-> *game-info* auto-save-count) 1)
|
|
)
|
|
)
|
|
(let ((v1-14 (-> self buffer)))
|
|
(set! (-> v1-14 current) (-> v1-14 base))
|
|
)
|
|
(let ((gp-0 loading-level))
|
|
(set! loading-level (-> self buffer))
|
|
(set! (-> self save) (new 'loading-level 'game-save #x10000))
|
|
(save-game! *game-info* (-> self save) "save")
|
|
(set! loading-level (the-as kheap gp-0))
|
|
0
|
|
(label cfg-7)
|
|
(set!
|
|
(-> self result)
|
|
(mc-save
|
|
(-> self card)
|
|
(-> self which)
|
|
(&-> (-> self save) type)
|
|
(the-as int (-> self save info-int32))
|
|
)
|
|
)
|
|
(when (!= (-> self result) (mc-status-code ok))
|
|
(suspend)
|
|
(goto cfg-7)
|
|
)
|
|
(while #t
|
|
(set! (-> self result) (the-as mc-status-code (mc-check-result)))
|
|
(let ((v1-24 (-> self result)))
|
|
(cond
|
|
((= v1-24 (mc-status-code busy))
|
|
#f
|
|
)
|
|
((= v1-24 (mc-status-code ok))
|
|
(goto cfg-21)
|
|
gp-0
|
|
)
|
|
((= v1-24 (mc-status-code write-error))
|
|
(suspend)
|
|
gp-0
|
|
)
|
|
(else
|
|
(case (-> self mode)
|
|
(('auto-save)
|
|
(set!
|
|
(-> *game-info* auto-save-count)
|
|
(seekl (-> *game-info* auto-save-count) 0 1)
|
|
)
|
|
)
|
|
)
|
|
(go-virtual error (-> self result))
|
|
)
|
|
|
|
)
|
|
)
|
|
(suspend)
|
|
)
|
|
)
|
|
(label cfg-21)
|
|
(go-virtual done)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate restore (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(local-vars (gp-0 none))
|
|
(cond
|
|
((zero? (-> self info formatted))
|
|
(go-virtual error (mc-status-code no-format))
|
|
)
|
|
((zero? (-> self info inited))
|
|
(go-virtual error (mc-status-code no-file))
|
|
)
|
|
)
|
|
(let ((v1-10 (-> self buffer)))
|
|
(set! (-> v1-10 current) (-> v1-10 base))
|
|
)
|
|
(if (zero? (-> self info file (-> self which) present))
|
|
(go-virtual error (mc-status-code no-save))
|
|
)
|
|
(label cfg-6)
|
|
(set!
|
|
(-> self result)
|
|
(mc-load (-> self card) (-> self which) (-> self buffer base))
|
|
)
|
|
(when (!= (-> self result) (mc-status-code ok))
|
|
(suspend)
|
|
(goto cfg-6)
|
|
)
|
|
(while #t
|
|
(set! (-> self result) (the-as mc-status-code (mc-check-result)))
|
|
(let ((v1-22 (-> self result)))
|
|
(cond
|
|
((= v1-22 (mc-status-code busy))
|
|
#f
|
|
)
|
|
((= v1-22 (mc-status-code ok))
|
|
(goto cfg-20)
|
|
gp-0
|
|
)
|
|
((= v1-22 (mc-status-code read-error))
|
|
(suspend)
|
|
gp-0
|
|
)
|
|
((= v1-22 (mc-status-code new-game))
|
|
(go-virtual error (mc-status-code no-save))
|
|
)
|
|
(else
|
|
(go-virtual error (-> self result))
|
|
)
|
|
)
|
|
|
|
)
|
|
(suspend)
|
|
)
|
|
(label cfg-20)
|
|
(set! (-> self save) (the-as game-save (&+ (-> self buffer base) 4)))
|
|
(let ((v1-34 (-> self save)))
|
|
(set! (-> v1-34 type) game-save)
|
|
(if (!= (-> v1-34 version) 1)
|
|
(go-virtual error (mc-status-code bad-version))
|
|
)
|
|
)
|
|
(set-setting! *setting-control* self 'music-volume 'abs 0.0 0)
|
|
(set-setting! *setting-control* self 'sfx-volume 'abs 0.0 0)
|
|
(set! (-> *game-info* mode) 'play)
|
|
(initialize! *game-info* 'game (-> self save) (the-as string #f))
|
|
(set-master-mode 'game)
|
|
(push-setting! *setting-control* self 'process-mask 'set 0.0 16)
|
|
(copy-settings-from-target! *setting-control*)
|
|
(dotimes (gp-1 15)
|
|
(suspend)
|
|
)
|
|
(go-virtual done)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defstate error (auto-save)
|
|
:virtual #t
|
|
:event
|
|
(behavior ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
|
|
(let ((v1-0 arg2))
|
|
(the-as object (cond
|
|
((= v1-0 'progress-allowed?)
|
|
#t
|
|
)
|
|
((= v1-0 'die)
|
|
(deactivate self)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
:code
|
|
(behavior ((arg0 mc-status-code))
|
|
(if (-> self buffer)
|
|
(reserve-free *art-control* (-> self buffer))
|
|
)
|
|
(set! (-> self result) arg0)
|
|
(let ((s5-0 *auto-save-info*))
|
|
(mem-copy! (the-as pointer s5-0) (the-as pointer (-> self info)) 300)
|
|
(send-event (handle->process (-> self notify)) 'notify 'error (-> self result) s5-0)
|
|
)
|
|
(let ((t9-3 format)
|
|
(a0-7 #t)
|
|
(a1-3 "SAVE ERROR: ~A~%")
|
|
(v1-12 (-> self result))
|
|
)
|
|
(t9-3 a0-7 a1-3 (cond
|
|
((= v1-12 (mc-status-code no-auto-save))
|
|
"no-auto-save"
|
|
)
|
|
((= v1-12 (mc-status-code no-process))
|
|
"no-process"
|
|
)
|
|
((= v1-12 (mc-status-code bad-version))
|
|
"bad-version"
|
|
)
|
|
((= v1-12 (mc-status-code no-space))
|
|
"no-space"
|
|
)
|
|
((= v1-12 (mc-status-code no-save))
|
|
"no-save"
|
|
)
|
|
((= v1-12 (mc-status-code no-file))
|
|
"no-file"
|
|
)
|
|
((= v1-12 (mc-status-code no-format))
|
|
"no-format"
|
|
)
|
|
((= v1-12 (mc-status-code no-last))
|
|
"no-last"
|
|
)
|
|
((= v1-12 (mc-status-code no-card))
|
|
"no-card"
|
|
)
|
|
((= v1-12 (mc-status-code no-memory))
|
|
"no-memory"
|
|
)
|
|
((= v1-12 (mc-status-code new-game))
|
|
"new-game"
|
|
)
|
|
((= v1-12 (mc-status-code read-error))
|
|
"read-error"
|
|
)
|
|
((= v1-12 (mc-status-code write-error))
|
|
"write-error"
|
|
)
|
|
((= v1-12 (mc-status-code internal-error))
|
|
"internal-error"
|
|
)
|
|
((= v1-12 (mc-status-code format-failed))
|
|
"format-failed"
|
|
)
|
|
((= v1-12 (mc-status-code bad-handle))
|
|
"bad-handle"
|
|
)
|
|
((= v1-12 (mc-status-code ok))
|
|
"ok"
|
|
)
|
|
((= v1-12 (mc-status-code busy))
|
|
"busy"
|
|
)
|
|
(else
|
|
"*unknown*"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(if (= (-> self result) (mc-status-code no-auto-save))
|
|
(return #f)
|
|
)
|
|
(case (-> self mode)
|
|
(('auto-save 'error)
|
|
(set! (-> self state-time) (-> *display* real-frame-counter))
|
|
(set! (-> *game-info* auto-save-status) arg0)
|
|
(while (< (- (-> *display* real-frame-counter) (-> self state-time)) 60)
|
|
(if (not (progress-allowed?))
|
|
(set! (-> self state-time) (-> *display* real-frame-counter))
|
|
)
|
|
(suspend)
|
|
)
|
|
(if (= arg0 (mc-status-code no-card))
|
|
(activate-progress *dproc* (progress-screen memcard-removed))
|
|
(activate-progress *dproc* (progress-screen memcard-auto-save-error))
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
;; failed to figure out what this is:
|
|
(defstate done (auto-save)
|
|
:virtual #t
|
|
:code
|
|
(behavior ()
|
|
(if (and (-> self buffer) (-> *art-control* reserve-buffer))
|
|
(reserve-free *art-control* (-> self buffer))
|
|
)
|
|
(set! (-> *game-info* auto-save-status) (mc-status-code ok))
|
|
(case (-> self mode)
|
|
(('save 'save-last 'auto-save 'restore)
|
|
(set! (-> *setting-control* default auto-save) #t)
|
|
(set! (-> *game-info* auto-save-card) (-> self card))
|
|
(set! (-> *game-info* auto-save-which) (-> self which))
|
|
)
|
|
)
|
|
(let ((gp-0 *auto-save-info*))
|
|
(mem-copy! (the-as pointer gp-0) (the-as pointer (-> self info)) 300)
|
|
(send-event (handle->process (-> self notify)) 'notify 'done 1 gp-0)
|
|
)
|
|
(case (-> self mode)
|
|
(('auto-save)
|
|
(when (= (-> *game-info* auto-save-count) 1)
|
|
(set! (-> self event-hook) (-> (method-of-object self error) event))
|
|
(set! (-> self state-time) (-> *display* real-frame-counter))
|
|
(while (< (- (-> *display* real-frame-counter) (-> self state-time)) 60)
|
|
(if (not (progress-allowed?))
|
|
(set! (-> self state-time) (-> *display* real-frame-counter))
|
|
)
|
|
(suspend)
|
|
)
|
|
(activate-progress *dproc* (progress-screen auto-save))
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
:post
|
|
auto-save-post
|
|
)
|
|
|
|
(defun auto-save-command ((arg0 symbol) (arg1 int) (arg2 int) (arg3 process-tree))
|
|
(format #t "auto-save cmd: ~A from ~A~%" arg0 arg3)
|
|
(make-init-process auto-save auto-save-init-by-other arg0 arg3 arg1 arg2)
|
|
(none)
|
|
)
|
|
|
|
(defun auto-save-check ()
|
|
(when (and (-> *setting-control* current auto-save)
|
|
(not (handle->process (-> *game-info* auto-save-proc)))
|
|
)
|
|
(mc-get-slot-info 0 *auto-save-info*)
|
|
(if (and (nonzero? (-> *auto-save-info* known))
|
|
(or (zero? (-> *auto-save-info* handle))
|
|
(!= (-> *auto-save-info* handle) (-> *game-info* auto-save-card))
|
|
)
|
|
)
|
|
(auto-save-command 'error 0 0 (the-as process *default-pool*))
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|