castleraider
changeset 323:e4cdff52b4a0
Moved some routines to the loader where they are copied down into working
memory, ready to be used by the game itself. This frees up memory in the main
game code and also makes them available for use in both the loader and
the game.
Ensured that temporary files are deleted as they are used or after the game
has been built.
| author | David Boddie <david@boddie.org.uk> |
|---|---|
| date | Sat Oct 04 20:48:08 2014 +0200 |
| parents | 6f53862eb4f7 |
| children | 5ecff9e25e1c |
| files | build.py code.oph ending.oph loader.oph |
| diffstat | 4 files changed, 203 insertions(+), 102 deletions(-) [+] |
line diff
1.1 --- a/build.py Sat Oct 04 01:13:43 2014 +0200 1.2 +++ b/build.py Sat Oct 04 20:48:08 2014 +0200 1.3 @@ -76,6 +76,16 @@ 1.4 1.5 return data_oph, text_length 1.6 1.7 +def encode_data(bytes): 1.8 + 1.9 + data = [] 1.10 + i = 0 1.11 + while i < len(bytes): 1.12 + 1.13 + data.append(".byte " + ",".join(map(lambda x: "$%02x" % ord(x), bytes[i:i+24]))) 1.14 + i += 24 1.15 + 1.16 + return "\n".join(data) 1.17 1.18 tiles = map(lambda tile: makelevels.tile_ref[tile], makelevels.tile_order) 1.19 1.20 @@ -89,6 +99,135 @@ 1.21 1.22 life_sprites = ["images/life1.png", "images/life2.png"] 1.23 1.24 +title_data_oph_routines = [ 1.25 +("print_title_text", """ 1.26 + 1.27 + ldx #[%(in_game_title_text_length)i - 1] 1.28 + title_text_loop: 1.29 + lda $%(in_game_title_text_address)x,x 1.30 + jsr $ffee 1.31 + dex 1.32 + bpl title_text_loop 1.33 + 1.34 + clc 1.35 + rts 1.36 +"""), 1.37 +("print_game_over_text", """ 1.38 + 1.39 + ldx #[%(in_game_game_over_text_length)i - 1] 1.40 + game_over_text_loop: 1.41 + lda $%(in_game_game_over_text_address)x,x 1.42 + jsr $ffee 1.43 + dex 1.44 + bpl game_over_text_loop 1.45 + 1.46 + clc 1.47 + rts 1.48 +""")] 1.49 + 1.50 +def encode_in_game_data(in_game_data_address): 1.51 + 1.52 + # Encode the in-game title data. 1.53 + title_data_oph = "" 1.54 + 1.55 + title_rows = 0 1.56 + for line in open("title.txt").readlines(): 1.57 + 1.58 + line = line.rstrip("\n") 1.59 + title_data_oph += ".byte " 1.60 + 1.61 + for i in range(0, 40, 4): 1.62 + 1.63 + byte = 0 1.64 + shift = 0 1.65 + for char in line[i:i + 4]: 1.66 + byte = byte | (".@#+".index(char) << shift) 1.67 + shift += 2 1.68 + 1.69 + title_data_oph += "$%02x" % byte 1.70 + if i < 36: 1.71 + title_data_oph += ", " 1.72 + 1.73 + title_data_oph += "\n" 1.74 + title_rows += 1 1.75 + 1.76 + title_data_oph += "\n" 1.77 + 1.78 + title_text = [(26, 31, 3, 6, 17, 3, "Retro Software"), 1.79 + (31, 6, 8, "presents"), 1.80 + (31, 2, 27, 17, 2, "Press ", 17, 3, "SPACE/FIRE"), 1.81 + (31, 6, 29, 17, 2, "to play")] 1.82 + 1.83 + title_data, in_game_title_text_length = encode_text(title_text) 1.84 + title_data_oph += title_data 1.85 + title_data_oph += '\n' 1.86 + 1.87 + game_over_text = [(26, 31, 1, 16, 17, 3, "Your quest is over"), 1.88 + (31, 4, 29, 17, 1, "Press SPACE")] 1.89 + 1.90 + game_over_data, in_game_game_over_text_length = encode_text(game_over_text) 1.91 + title_data_oph += game_over_data 1.92 + title_data_oph += '\n' 1.93 + 1.94 + in_game_title_text_address = in_game_data_address + (title_rows * 10) 1.95 + in_game_game_over_text_address = in_game_title_text_address + in_game_title_text_length 1.96 + in_game_title_routines_address = in_game_game_over_text_address + in_game_game_over_text_length 1.97 + 1.98 + labels = ( 1.99 + ".alias title_data_address $%(title_data_address)x\n" 1.100 + ".alias title_rows %(title_rows)i\n" 1.101 + ".alias in_game_title_text_address $%(in_game_title_text_address)x\n" 1.102 + ".alias in_game_title_text_length %(in_game_title_text_length)i\n" 1.103 + ".alias in_game_game_over_text_address $%(in_game_game_over_text_address)x\n" 1.104 + ".alias in_game_game_over_text_length %(in_game_game_over_text_length)i\n" 1.105 + ".alias in_game_completion_address $%(in_game_completion_address)x\n" 1.106 + ) 1.107 + 1.108 + details = { 1.109 + "title_data_address": in_game_data_address, 1.110 + "title_rows": title_rows, 1.111 + "in_game_title_text_address": in_game_title_text_address, 1.112 + "in_game_title_text_length": in_game_title_text_length, 1.113 + "in_game_game_over_text_address": in_game_game_over_text_address, 1.114 + "in_game_game_over_text_length": in_game_game_over_text_length, 1.115 + } 1.116 + 1.117 + routine_address = in_game_title_routines_address 1.118 + for name, routine in title_data_oph_routines: 1.119 + 1.120 + routine = name + ":" + (routine % details) 1.121 + open("temp.oph", "w").write(routine) 1.122 + system("ophis temp.oph -o TEMP") 1.123 + 1.124 + # Include the routine in the title data file. 1.125 + title_data_oph += routine + "\n" 1.126 + 1.127 + # Add the run-time address to the constants. 1.128 + labels += ".alias " + name + "_address" + (" $%0x\n" % routine_address) 1.129 + details[name + "_address"] = routine_address 1.130 + 1.131 + # Update the routine address. 1.132 + routine_address += os.stat("TEMP")[stat.ST_SIZE] 1.133 + 1.134 + os.remove("temp.oph") 1.135 + os.remove("TEMP") 1.136 + 1.137 + # The completion code is stored after the title routines. 1.138 + details["in_game_completion_address"] = routine_address 1.139 + 1.140 + ending = open("ending.oph").read() 1.141 + ending = ending % {"in_game_completion_address": routine_address} 1.142 + open("temp.oph", "w").write(ending) 1.143 + 1.144 + system("ophis temp.oph -o TEMP") 1.145 + ending = open("TEMP").read() 1.146 + os.remove("temp.oph") 1.147 + os.remove("TEMP") 1.148 + title_data_oph += encode_data(ending) 1.149 + 1.150 + open("title-data-and-ending.oph", "w").write(title_data_oph) 1.151 + 1.152 + return labels, details 1.153 1.154 if __name__ == "__main__": 1.155 1.156 @@ -112,57 +251,6 @@ 1.157 else: 1.158 level_file = sys.argv[4] 1.159 1.160 - # Encode the in-game title data. 1.161 - title_data_oph = "title_data:\n" 1.162 - 1.163 - title_rows = 0 1.164 - for line in open("title.txt").readlines(): 1.165 - 1.166 - line = line.rstrip("\n") 1.167 - title_data_oph += ".byte " 1.168 - 1.169 - for i in range(0, 40, 4): 1.170 - 1.171 - byte = 0 1.172 - shift = 0 1.173 - for char in line[i:i + 4]: 1.174 - byte = byte | (".@#+".index(char) << shift) 1.175 - shift += 2 1.176 - 1.177 - title_data_oph += "$%02x" % byte 1.178 - if i < 36: 1.179 - title_data_oph += ", " 1.180 - 1.181 - title_data_oph += "\n" 1.182 - title_rows += 1 1.183 - 1.184 - title_data_oph += ( 1.185 - "\n" 1.186 - "title_end:\n" 1.187 - ".alias title_length [title_end - title_data]\n" 1.188 - "\n" 1.189 - ) 1.190 - 1.191 - title_text = [(26, 31, 3, 6, 17, 3, "Retro Software"), 1.192 - (31, 6, 8, "presents"), 1.193 - (31, 2, 27, 17, 2, "Press ", 17, 3, "SPACE/FIRE"), 1.194 - (31, 6, 29, 17, 2, "to play")] 1.195 - 1.196 - title_data_oph += 'game_title_text:\n' 1.197 - title_data, in_game_title_text_length = encode_text(title_text) 1.198 - title_data_oph += title_data 1.199 - title_data_oph += 'game_title_text_end:\n' 1.200 - 1.201 - game_over_text = [(26, 31, 1, 16, 17, 3, "Your quest is over"), 1.202 - (31, 4, 29, 17, 1, "Press SPACE")] 1.203 - 1.204 - title_data_oph += 'game_over_text:\n' 1.205 - game_over_data, in_game_game_over_text_length = encode_text(game_over_text) 1.206 - title_data_oph += game_over_data 1.207 - title_data_oph += 'game_over_text_end:\n' 1.208 - 1.209 - open("title-data.oph", "w").write(title_data_oph) 1.210 - 1.211 # Memory map 1.212 memory_map = { 1.213 "working area": 0xb00, 1.214 @@ -238,11 +326,8 @@ 1.215 # data - this is done in the loader. 1.216 title_data_address = initial_row_offsets + 0x10 1.217 1.218 - in_game_title_text_address = title_data_address + (title_rows * 10) 1.219 - in_game_game_over_text_address = in_game_title_text_address + in_game_title_text_length 1.220 - in_game_completion_address = in_game_game_over_text_address + in_game_game_over_text_length 1.221 - 1.222 - working_end = in_game_completion_address 1.223 + in_game_data_labels, in_game_data_details = encode_in_game_data(title_data_address) 1.224 + working_end = in_game_data_details["in_game_completion_address"] 1.225 1.226 # Permanent data 1.227 1.228 @@ -551,19 +636,7 @@ 1.229 monster_right_offset, 1.230 monster_right_max_offset) 1.231 1.232 - constants_oph += ( 1.233 - ".alias title_data_address $%x\n" 1.234 - ".alias title_rows %i\n" 1.235 - ".alias in_game_title_text_address $%x\n" 1.236 - ".alias in_game_title_text_length %i\n" 1.237 - ".alias in_game_game_over_text_address $%x\n" 1.238 - ".alias in_game_game_over_text_length %i\n" 1.239 - ".alias in_game_total_text_length %i\n" 1.240 - "\n" 1.241 - ) % (title_data_address, title_rows, 1.242 - in_game_title_text_address, in_game_title_text_length, 1.243 - in_game_game_over_text_address, in_game_game_over_text_length, 1.244 - in_game_title_text_length + in_game_game_over_text_length) 1.245 + constants_oph += (in_game_data_labels % in_game_data_details) + "\n" 1.246 1.247 scenery_rows = 16 1.248 extra_rows = 7 1.249 @@ -620,6 +693,7 @@ 1.250 1.251 system("ophis code.oph -o CODE") 1.252 code = open("CODE").read() 1.253 + os.remove("CODE") 1.254 1.255 loader_start = 0x3500 1.256 1.257 @@ -662,6 +736,7 @@ 1.258 1.259 system("ophis loader.oph -o LOADER") 1.260 loader_code = open("LOADER").read() + markers + title_data 1.261 + os.remove("LOADER") 1.262 1.263 bootloader_start = 0xe00 1.264 bootloader_code = ("\r\x00\x0a\x0d*FX 229,1" 1.265 @@ -683,14 +758,20 @@ 1.266 # uncompressed = c.uncompress(compressed) 1.267 # print info[0], len(data), len(compressed), data == uncompressed 1.268 1.269 - loader_size = os.stat("LOADER")[stat.ST_SIZE] 1.270 + loader_size = len(loader_code) 1.271 print 1.272 print "%i bytes (%04x) of loader code" % (loader_size, loader_size) 1.273 1.274 - code_size = os.stat("CODE")[stat.ST_SIZE] 1.275 + code_size = len(code) 1.276 print "%i bytes (%04x) of code" % (code_size, code_size) 1.277 print 1.278 1.279 + # Calculate the amount of space used for the loader. 1.280 + 1.281 + loader_finish = loader_start + loader_size 1.282 + print "LOADER runs from %04x to %04x" % (loader_start, loader_finish) 1.283 + print 1.284 + 1.285 # Calculate the amount of working space used. 1.286 1.287 print "Working data area runs from 0b00 to %04x (%i bytes free)" % (working_end, 0xd00 - working_end) 1.288 @@ -812,5 +893,12 @@ 1.289 print 1.290 print "Written", out_file 1.291 1.292 + # Remove temporary files. 1.293 + os.remove("bank_routines.oph") 1.294 + os.remove("constants.oph") 1.295 + os.remove("loader-constants.oph") 1.296 + os.remove("screen.oph") 1.297 + os.remove("title-data-and-ending.oph") 1.298 + 1.299 # Exit 1.300 sys.exit()
2.1 --- a/code.oph Sat Oct 04 01:13:43 2014 +0200 2.2 +++ b/code.oph Sat Oct 04 20:48:08 2014 +0200 2.3 @@ -30,12 +30,7 @@ 2.4 jsr show_bank2 ; Show bank 2 since this is where the output of OS 2.5 ; calls will appear. 2.6 2.7 - ldx #[in_game_title_text_length - 1] 2.8 - title_text_loop: 2.9 - lda in_game_title_text_address,x 2.10 - jsr $ffee 2.11 - dex 2.12 - bpl title_text_loop 2.13 + jsr print_title_text_address 2.14 2.15 ; Wait for the SPACE key or fire button to be pressed. 2.16 main_start_wait_loop: 2.17 @@ -194,7 +189,7 @@ 2.18 cmp #finish_scroll_offset_high 2.19 bne main_loop_check_monsters 2.20 2.21 - jmp game_completed 2.22 + jsr in_game_completion_address 2.23 2.24 main_loop_check_monsters: 2.25 jsr check_player_monsters 2.26 @@ -250,12 +245,7 @@ 2.27 jsr show_bank2 ; Show bank 2 since this is where the output of OS 2.28 ; calls will appear. 2.29 2.30 - ldx #[in_game_game_over_text_length - 1] 2.31 - game_over_text_loop: 2.32 - lda in_game_game_over_text_address,x 2.33 - jsr $ffee 2.34 - dex 2.35 - bpl game_over_text_loop 2.36 + jsr print_game_over_text_address 2.37 2.38 lda #157 ; (SPACE) 2.39 jsr wait_for_key 2.40 @@ -1099,14 +1089,6 @@ 2.41 sec 2.42 rts 2.43 2.44 -game_completed: 2.45 - 2.46 - ; Do something to indicate the game has been completed. 2.47 - ; Check whether the player found the treasures. 2.48 - 2.49 - clc 2.50 - rts 2.51 - 2.52 .include "screen.oph" 2.53 .include "plotting.oph" 2.54 .include "scrolling.oph"
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/ending.oph Sat Oct 04 20:48:08 2014 +0200 3.3 @@ -0,0 +1,28 @@ 3.4 +; Copyright (C) 2014 David Boddie <david@boddie.org.uk> 3.5 +; 3.6 +; This program is free software: you can redistribute it and/or modify 3.7 +; it under the terms of the GNU General Public License as published by 3.8 +; the Free Software Foundation, either version 3 of the License, or 3.9 +; (at your option) any later version. 3.10 +; 3.11 +; This program is distributed in the hope that it will be useful, 3.12 +; but WITHOUT ANY WARRANTY; without even the implied warranty of 3.13 +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3.14 +; GNU General Public License for more details. 3.15 +; 3.16 +; You should have received a copy of the GNU General Public License 3.17 +; along with this program. If not, see <http://www.gnu.org/licenses/>. 3.18 + 3.19 +; The following line contains a placeholder address that the build script 3.20 +; calculates and fills in. 3.21 +.org $%(in_game_completion_address)x 3.22 + 3.23 +game_completed: 3.24 + 3.25 + ; Do something to indicate the game has been completed. 3.26 + ; Check whether the player found the treasures. 3.27 + 3.28 + jmp game_completed 3.29 + 3.30 + clc 3.31 + rts
4.1 --- a/loader.oph Sat Oct 04 01:13:43 2014 +0200 4.2 +++ b/loader.oph Sat Oct 04 20:48:08 2014 +0200 4.3 @@ -117,12 +117,12 @@ 4.4 jsr tab_x_y 4.5 4.6 ldx #0 4.7 - title_text_loop: 4.8 + loader_title_text_loop: 4.9 lda title_text,x 4.10 jsr $ffee 4.11 inx 4.12 cpx #[title_text_end - title_text] 4.13 - bne title_text_loop 4.14 + bne loader_title_text_loop 4.15 4.16 ; Define ENVELOPEs. 4.17 lda #0 4.18 @@ -490,12 +490,9 @@ 4.19 4.20 move_title_data: 4.21 4.22 - ldx #0 4.23 - ldy #0 4.24 - 4.25 - lda #<title_data 4.26 + lda #<in_game_data_start 4.27 sta $70 4.28 - lda #>title_data 4.29 + lda #>in_game_data_start 4.30 sta $71 4.31 4.32 lda #<title_data_address 4.33 @@ -503,6 +500,7 @@ 4.34 lda #>title_data_address 4.35 sta $73 4.36 4.37 + ldy #0 4.38 move_title_data_loop: 4.39 4.40 clc 4.41 @@ -525,14 +523,19 @@ 4.42 sta $73 4.43 clc 4.44 4.45 - inx 4.46 - cpx #[title_length + in_game_total_text_length] 4.47 + lda $70 4.48 + cmp #<in_game_data_end 4.49 + bne move_title_data_loop 4.50 + lda $71 4.51 + cmp #>in_game_data_end 4.52 bne move_title_data_loop 4.53 4.54 clc 4.55 rts 4.56 4.57 -.include "title-data.oph" 4.58 +in_game_data_start: 4.59 +.include "title-data-and-ending.oph" 4.60 +in_game_data_end: 4.61 4.62 ; Flag drawing routines 4.63
