481 lines
11 KiB
NASM
481 lines
11 KiB
NASM
; Copyright (C) 2021 Christophe Meneboeuf <christophe@xtof.info>
|
|
;
|
|
; This program is free software: you can redistribute it and/or modify
|
|
; it under the terms of the GNU General Public License as published by
|
|
; the Free Software Foundation, either version 3 of the License, or
|
|
; (at your option) any later version.
|
|
;
|
|
; This program is distributed in the hope that it will be useful,
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
; GNU General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
; TODO a lot of code space can be spared by factorizing ReadState and Write state. Almos the same code
|
|
|
|
|
|
.include "../actors/actors.inc"
|
|
.include "../world/level.inc"
|
|
.include "../world/world.inc"
|
|
.include "../common.inc"
|
|
.include "../memory.inc"
|
|
.include "../math.inc"
|
|
|
|
.import World
|
|
.import ActorsInLevel
|
|
.import LevelIsBuilt
|
|
.import PlayerTile
|
|
.import Tile_player_standing_actor
|
|
|
|
; data
|
|
; TODO : should remain private!!
|
|
.export Str_FileLevelConfs
|
|
.export Str_FileLevelsActors
|
|
.export Param_FileOpen
|
|
.export Param_FileOffset
|
|
.export Param_FilesReadWrite
|
|
.export File_Buffer
|
|
|
|
|
|
; functions
|
|
.export ReadFile
|
|
.export LoadState
|
|
.export SaveState
|
|
.export ResetIsBuilt
|
|
.export LoadCurrentLevel
|
|
|
|
.define TO_PATCH 0
|
|
|
|
; reserve 1024 bytes for MLI file operations in the upper part of HGR2
|
|
File_Buffer := $5C00
|
|
|
|
|
|
.RODATA
|
|
|
|
Str_FileLevelConfs:
|
|
.byte $19, "/PRODOS.2.4.2/LEVELS.CONF" ; Pascal string
|
|
Str_FileLevelsActors:
|
|
.byte $19, "/PRODOS.2.4.2/LEVELS.ACTS" ; Pascal string
|
|
Str_FileStates:
|
|
.byte $14, "/PRODOS.2.4.2/STATES" ; Pascal string
|
|
|
|
.BSS
|
|
|
|
Lvl_Nr: .res 1
|
|
|
|
.define MIN_READ_SIZE 256
|
|
ReadWriteBuffer: .res MIN_READ_SIZE
|
|
|
|
.DATA
|
|
|
|
Param_FileOpen:
|
|
.byte $3 ; in - nb params
|
|
.addr TO_PATCH ; in - char* filepath
|
|
.addr File_Buffer ; in - char* workbuffer
|
|
Handle_File:
|
|
.byte $0 ; out - handle on the file
|
|
|
|
Param_FileOffset:
|
|
.byte $2 ; in - nb params
|
|
.byte TO_PATCH ; in - handle on the file
|
|
.byte TO_PATCH, TO_PATCH, 0 ; in - Offset
|
|
|
|
Param_FilesReadWrite:
|
|
.byte $4 ; in - nb params
|
|
.byte TO_PATCH ; in - handle on the file
|
|
.addr TO_PATCH ; in - out buffer
|
|
.word TO_PATCH ; in - max nb bytes to WRITE/READ
|
|
.word $0000 ; out - nb bytes write/read
|
|
|
|
Param_FileClose:
|
|
.byte $1 ; in - nb params
|
|
.byte TO_PATCH ; in - handle on the file
|
|
|
|
|
|
|
|
.CODE
|
|
|
|
; TODO handle errors
|
|
ReadFile:
|
|
|
|
; Open the file
|
|
jsr $BF00 ; call MLI
|
|
.byte $C8 ; Open
|
|
.addr Param_FileOpen
|
|
|
|
; Set read position
|
|
lda Handle_File
|
|
sta Param_FileOffset+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CE ; Set Mark
|
|
.addr Param_FileOffset
|
|
|
|
; Read the file
|
|
lda Handle_File
|
|
sta Param_FilesReadWrite+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CA ; read
|
|
.addr Param_FilesReadWrite
|
|
|
|
; Close the file
|
|
lda Handle_File
|
|
sta Param_FileClose+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CC ; Close
|
|
.addr Param_FileClose
|
|
rts
|
|
|
|
|
|
|
|
.define READ_DST ZERO_2_4 ; 2 bytes
|
|
|
|
; @brief Offset in A:X (little endian)
|
|
; HandleFile must have been set by opening the file
|
|
_SetOffset:
|
|
|
|
sta Param_FileOffset+2
|
|
stx Param_FileOffset+3
|
|
lda Handle_File
|
|
sta Param_FileOffset+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CE ; Set Mark
|
|
.addr Param_FileOffset
|
|
|
|
rts
|
|
|
|
; @brief Size in in A:X (little endian)
|
|
; Destination ptr in READ_DST: cannot be locate in ZERO PAGE!!!
|
|
; HandleFile must have been set by opening the file
|
|
_Read:
|
|
|
|
; Read the file
|
|
sta Param_FilesReadWrite+4
|
|
stx Param_FilesReadWrite+5
|
|
lda Handle_File
|
|
sta Param_FilesReadWrite+1
|
|
lda READ_DST
|
|
sta Param_FilesReadWrite+2
|
|
lda READ_DST+1
|
|
sta Param_FilesReadWrite+3
|
|
jsr $BF00 ; call MLI
|
|
.byte $CA ; read
|
|
.addr Param_FilesReadWrite
|
|
|
|
rts
|
|
|
|
; @param LevelNr in A
|
|
; @return isBuilt in A
|
|
; modifies ZERO_2_3, ZERO_2_4, ZERO_2_5
|
|
.define LVLS_HEADER_SIZE 4
|
|
.define LVL_HEADER_SIZE 3
|
|
.define OFFSET Param_FileOffset+2
|
|
; compute offset and sets file position
|
|
_FindLevelLayout:
|
|
|
|
; Compute the level state offset in file
|
|
ldy #(LVLS_HEADER_SIZE + 2 + LVL_HEADER_SIZE) ; +2: current lvl + nb lvls
|
|
sty OFFSET
|
|
lda #0
|
|
sta OFFSET+1
|
|
lda Lvl_Nr
|
|
tax
|
|
cpx #0
|
|
beq end_acc_offset_lvl
|
|
acc_offset_lvl:
|
|
ADD16 OFFSET, #<(HEIGHT_WORLD * WIDTH_WORLD), #>(HEIGHT_WORLD * WIDTH_WORLD)
|
|
ADD16 OFFSET, #(LVL_HEADER_SIZE + 2), #0 ; +2: visited + tile
|
|
dex
|
|
bne acc_offset_lvl
|
|
end_acc_offset_lvl:
|
|
|
|
; Set read position
|
|
lda OFFSET
|
|
ldx OFFSET+1
|
|
jsr _SetOffset
|
|
|
|
rts
|
|
|
|
|
|
.define ACTSS_HEADER_SIZE 4;
|
|
.define ACT_HEADER_SIZE 3;
|
|
_FindLevelActors:
|
|
|
|
; Compute offset
|
|
lda #(LVLS_HEADER_SIZE + 2)
|
|
sta OFFSET
|
|
lda #0
|
|
sta OFFSET+1
|
|
ldx NbLevels
|
|
acc_offset_lvls:
|
|
ADD16 OFFSET, #<(HEIGHT_WORLD * WIDTH_WORLD), #>(HEIGHT_WORLD * WIDTH_WORLD)
|
|
ADD16 OFFSET, #(LVL_HEADER_SIZE + 2), #0 ; +2: visited + tile
|
|
dex
|
|
bne acc_offset_lvls
|
|
ADD16 OFFSET, #(ACTSS_HEADER_SIZE + ACT_HEADER_SIZE), #0
|
|
|
|
ldx Lvl_Nr
|
|
cpx #0
|
|
beq end_acc_offset_actors
|
|
acc_offset_actors:
|
|
ADD16 OFFSET, #<(ACT_HEADER_SIZE + SIZEOF_ACTORS_T), #>(ACT_HEADER_SIZE + SIZEOF_ACTORS_T)
|
|
dex
|
|
bne acc_offset_actors
|
|
end_acc_offset_actors:
|
|
|
|
; Set read position
|
|
lda OFFSET
|
|
ldx OFFSET+1
|
|
jsr _SetOffset
|
|
|
|
rts
|
|
|
|
; @param Level NR in A
|
|
LoadState:
|
|
|
|
sta Lvl_Nr
|
|
|
|
; Open the file
|
|
lda #<Str_FileStates
|
|
sta Param_FileOpen+1
|
|
lda #>Str_FileStates
|
|
sta Param_FileOpen+2
|
|
jsr $BF00 ; call MLI
|
|
.byte $C8 ; Open
|
|
.addr Param_FileOpen
|
|
|
|
; save the new current level
|
|
lda #(LVLS_HEADER_SIZE)
|
|
ldx #0
|
|
jsr _SetOffset ; current lvl
|
|
lda #<Lvl_Nr
|
|
sta READ_DST
|
|
lda #>Lvl_Nr
|
|
sta READ_DST+1
|
|
lda #1
|
|
ldx #0
|
|
jsr _Write
|
|
|
|
lda Lvl_Nr
|
|
jsr _FindLevelLayout ; compute offset and sets file read position
|
|
|
|
lda #<ReadWriteBuffer
|
|
sta READ_DST
|
|
lda #>ReadWriteBuffer
|
|
sta READ_DST+1
|
|
lda #<MIN_READ_SIZE
|
|
ldx #>MIN_READ_SIZE
|
|
jsr _Read
|
|
lda ReadWriteBuffer
|
|
sta LevelIsBuilt
|
|
lda ReadWriteBuffer+1
|
|
sta Tile_player_standing_actor
|
|
|
|
lda LevelIsBuilt
|
|
cmp #FALSE
|
|
beq LoadState_end
|
|
|
|
; Read the level's layout
|
|
; Set read position
|
|
ADD16 OFFSET, #2, #0 ; offset past "visited" & "tile"
|
|
lda OFFSET
|
|
ldx OFFSET+1
|
|
jsr _SetOffset
|
|
; Read the file
|
|
lda #<World
|
|
sta READ_DST
|
|
lda #>World
|
|
sta READ_DST+1
|
|
lda #<(HEIGHT_WORLD * WIDTH_WORLD)
|
|
ldx #>(HEIGHT_WORLD * WIDTH_WORLD)
|
|
jsr _Read
|
|
|
|
; Read level actors state
|
|
jsr _FindLevelActors ; compute offset and sets file read position
|
|
; Read the file
|
|
lda #<ActorsInLevel
|
|
sta READ_DST
|
|
lda #>ActorsInLevel
|
|
sta READ_DST+1
|
|
lda #<(SIZEOF_ACTORS_T)
|
|
ldx #>(SIZEOF_ACTORS_T)
|
|
jsr _Read
|
|
|
|
LoadState_end:
|
|
|
|
; Close the file
|
|
lda Handle_File
|
|
sta Param_FileClose+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CC ; Close
|
|
.addr Param_FileClose
|
|
|
|
rts
|
|
|
|
|
|
|
|
.define WRITE_DST ZERO_2_4 ; 2 bytes
|
|
; @brief Size in in A:X (little endian)
|
|
; Destination ptr in WRITE_DST: cannot be locate in ZERO PAGE!!!
|
|
; HandleFile must have been set by opening the file
|
|
_Write:
|
|
|
|
; Wr the file
|
|
sta Param_FilesReadWrite+4
|
|
stx Param_FilesReadWrite+5
|
|
lda Handle_File
|
|
sta Param_FilesReadWrite+1
|
|
lda WRITE_DST
|
|
sta Param_FilesReadWrite+2
|
|
lda WRITE_DST+1
|
|
sta Param_FilesReadWrite+3
|
|
jsr $BF00 ; call MLI
|
|
.byte $CB ; write
|
|
.addr Param_FilesReadWrite
|
|
|
|
rts
|
|
|
|
|
|
; @param Level NR in A
|
|
SaveState:
|
|
|
|
sta Lvl_Nr
|
|
|
|
; Open the file
|
|
lda #<Str_FileStates
|
|
sta Param_FileOpen+1
|
|
lda #>Str_FileStates
|
|
sta Param_FileOpen+2
|
|
jsr $BF00 ; call MLI
|
|
.byte $C8 ; Open
|
|
.addr Param_FileOpen
|
|
|
|
lda Lvl_Nr
|
|
jsr _FindLevelLayout ; compute offset and sets file write position
|
|
|
|
; Write the file
|
|
lda #TRUE
|
|
sta ReadWriteBuffer
|
|
lda Tile_player_standing_actor
|
|
sta ReadWriteBuffer+1
|
|
lda #<ReadWriteBuffer
|
|
sta WRITE_DST
|
|
lda #>ReadWriteBuffer
|
|
sta WRITE_DST+1
|
|
lda #<MIN_READ_SIZE
|
|
ldx #>MIN_READ_SIZE
|
|
jsr _Write
|
|
|
|
; Write the level's layout
|
|
; Set write position
|
|
ADD16 OFFSET, #2, #0 ; offset past "visited" & "tile"
|
|
lda OFFSET
|
|
ldx OFFSET+1
|
|
jsr _SetOffset
|
|
; Write the file
|
|
lda #<World
|
|
sta WRITE_DST
|
|
lda #>World
|
|
sta WRITE_DST+1
|
|
lda #<(HEIGHT_WORLD * WIDTH_WORLD)
|
|
ldx #>(HEIGHT_WORLD * WIDTH_WORLD)
|
|
jsr _Write
|
|
|
|
; Write level actors state
|
|
jsr _FindLevelActors ; compute offset and sets file write position
|
|
; Write the file
|
|
lda #<ActorsInLevel
|
|
sta WRITE_DST
|
|
lda #>ActorsInLevel
|
|
sta WRITE_DST+1
|
|
lda #<(SIZEOF_ACTORS_T)
|
|
ldx #>(SIZEOF_ACTORS_T)
|
|
jsr _Write
|
|
|
|
; Close the file
|
|
lda Handle_File
|
|
sta Param_FileClose+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CC ; Close
|
|
.addr Param_FileClose
|
|
|
|
rts
|
|
|
|
; @param LevelNr in A
|
|
ResetIsBuilt:
|
|
|
|
sta Lvl_Nr
|
|
|
|
; Open the file
|
|
lda #<Str_FileStates
|
|
sta Param_FileOpen+1
|
|
lda #>Str_FileStates
|
|
sta Param_FileOpen+2
|
|
jsr $BF00 ; call MLI
|
|
.byte $C8 ; Open
|
|
.addr Param_FileOpen
|
|
|
|
for_each_lvl:
|
|
dec Lvl_Nr
|
|
jsr _FindLevelLayout ; compute offset and sets file write position
|
|
inc Lvl_Nr
|
|
|
|
lda #FALSE
|
|
sta ReadWriteBuffer
|
|
lda #<ReadWriteBuffer
|
|
sta WRITE_DST
|
|
lda #>ReadWriteBuffer
|
|
sta WRITE_DST+1
|
|
lda #<MIN_READ_SIZE
|
|
ldx #>MIN_READ_SIZE
|
|
jsr _Write
|
|
|
|
dec Lvl_Nr
|
|
bne for_each_lvl
|
|
|
|
; Close the file
|
|
lda Handle_File
|
|
sta Param_FileClose+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CC ; Close
|
|
.addr Param_FileClose
|
|
|
|
rts
|
|
|
|
|
|
|
|
LoadCurrentLevel:
|
|
|
|
; Open the file
|
|
lda #<Str_FileStates
|
|
sta Param_FileOpen+1
|
|
lda #>Str_FileStates
|
|
sta Param_FileOpen+2
|
|
jsr $BF00 ; call MLI
|
|
.byte $C8 ; Open
|
|
.addr Param_FileOpen
|
|
|
|
; load the current level
|
|
lda #(LVLS_HEADER_SIZE)
|
|
ldx #0
|
|
jsr _SetOffset ; current lvl
|
|
lda #<ReadWriteBuffer
|
|
sta READ_DST
|
|
lda #>ReadWriteBuffer
|
|
sta READ_DST+1
|
|
lda #<MIN_READ_SIZE
|
|
ldx #>MIN_READ_SIZE
|
|
jsr _Read
|
|
lda ReadWriteBuffer
|
|
sta NextLevel
|
|
|
|
; Close the file
|
|
lda Handle_File
|
|
sta Param_FileClose+1
|
|
jsr $BF00 ; call MLI
|
|
.byte $CC ; Close
|
|
.addr Param_FileClose
|
|
|
|
rts |