/[projet1]/public/oric/demos/OricTech/code/loader.asm
Defence Force logotype

Contents of /public/oric/demos/OricTech/code/loader.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1398 - (show annotations)
Sun Apr 9 18:38:29 2017 UTC (2 years, 5 months ago) by Jede
File size: 13653 byte(s)
Telestrat bug corrected


1
2 #define OPCODE_RTS $60
3 #define OPCODE_JMP $4C
4
5 #define COLOR(color) pha:lda #16+(color&7):sta $bb80+40*27:pla
6 #define STOP(color) pha:lda #16+(color&7):sta $bb80+40*27:jmp *:pla
7
8 ;
9 ; VIA registers definition
10 ;
11 #define via_portb $0300
12 #define via_ddrb $0302
13 #define via_ddra $0303
14 #define via_t1cl $0304
15 #define via_t1ch $0305
16 #define via_t1ll $0306
17 #define via_t1lh $0307
18 #define via_t2ll $0308
19 #define via_t2ch $0309
20 #define via_sr $030a
21 #define via_acr $030b
22 #define via_pcr $030c
23 #define via_ifr $030d
24 #define via_ier $030e
25 #define via_porta $030f
26
27
28 ;
29 ; Microdisc register values
30 ;
31 #define FDC_command_register $0310
32 #define FDC_status_register $0310
33 #define FDC_track_register $0311
34 #define FDC_sector_register $0312
35 #define FDC_data $0313
36 #define FDC_flags $0314
37 #define FDC_drq $0318
38
39 #define FDC_Flags_Mask %10000100 ; Disable ROM/EPROM, no FDC interrupt requests, A drive, Side 0
40 #define FDC_Flag_DiscSide %00010000 ; Accesses second side of the disk
41
42 #define CMD_ReadSector $80
43
44 #define CMD_Seek $1F
45
46 #define wait_status_floppy 30
47
48
49 ;
50 ; Jasmin register values
51 ;
52 #define FDC_JASMIN_command_register $03f4
53 #define FDC_JASMIN_status_register $03f4
54 #define FDC_JASMIN_track_register $03f5
55 #define FDC_JASMIN_sector_register $03f6
56 #define FDC_JASMIN_data $03f7
57 #define FDC_JASMIN_flags $03f8
58 #define FDC_JASMIN_drq $03FC
59
60 #define FDC_JASMIN_Flag_DiscSide %00000001
61
62 #define CMD_JASMIN_ReadSector $8c
63
64
65 #include "floppy_description.h" ; This file is generated by the floppy builder
66
67 .zero
68
69 *=LOADER_BASE_ZERO_PAGE
70 ; If you add or remove any variables, make sure that LOADER_BASE_ZERO_PAGE is still correct (defined in the floppy builder script)
71 current_track .dsb 1 ; Index of the track being loaded
72 current_sector .dsb 1 ; Index of the sector being loaded
73 current_side .dsb 1 ; Has the bit 4 set to 0 or 1 to be used as a mask on the Microdisc control register (other bits have to be set to zero)
74
75 ptr_destination .dsb 2 ; Destination adress where we depack
76 ptr_destination_end .dsb 2 ; Point on the end of the depacked stuff
77 ptr_source_back .dsb 2 ; Temporary used to hold a pointer on depacked stuff
78 offset .dsb 2
79 mask_value .dsb 1
80 nb_dst .dsb 1
81
82 .text
83
84 *=FLOPPY_LOADER_ADDRESS
85
86 ; ------------------------------------------------------------------------------
87 ; Startup section
88 ; ------------------------------------------------------------------------------
89 ;
90 ; This section of the loader can be overwritten after the loader has been installed in memory.
91 ; It contains initialization code that just need to be run once at the start of the application.
92 ; If there are specific initialization, setup of video mode, etc... you need to do, that's the place.
93 ;
94 ; By default the Microdisc/Jasmin setup code is performed here:
95 ; The code of the loader is setup to load things from a Microdisc, but if we are called with X not null,
96 ; then we patch all the values to replace them by Jasmin equivalents
97 ;
98 _LoaderTemporaryStart
99 sei ; Make sure interrupts are disabled
100 cld ; Force decimal mode
101
102 cpx #0 ; If we are on Jasmin, patch all the FDC related values
103 beq end_jasmin_init
104
105 lda #<FDC_JASMIN_command_register
106 sta 1+__fdc_command_1
107 sta 1+__fdc_command_2
108
109 lda #<FDC_JASMIN_status_register
110 sta 1+__fdc_status_1
111 sta 1+__fdc_status_2
112
113 lda #<FDC_JASMIN_track_register
114 sta 1+__fdc_track_1
115
116 lda #<FDC_JASMIN_sector_register
117 sta 1+__fdc_sector_1
118
119 lda #<FDC_JASMIN_data
120 sta 1+__fdc_data_1
121 sta 1+__fdc_data_2
122
123 lda #<FDC_JASMIN_flags
124 sta 1+__fdc_flags_1
125 sta 1+__fdc_flags_2
126
127 lda #<FDC_JASMIN_drq
128 sta 1+__fdc_drq_1
129
130 lda #CMD_JASMIN_ReadSector
131 sta 1+__fdc_readsector
132
133 lda #FDC_JASMIN_Flag_DiscSide
134 sta 1+__fdc_discside
135
136 end_jasmin_init
137
138 ldx #$ff ; Reset the stack pointer
139 txs
140
141 lda #$ff ; Initialize the VIA to known values (code is from Atmos ROM)
142 sta via_ddra
143 lda #$f7
144 sta via_ddrb
145 lda #$b7
146 sta via_portb
147 lda #$dd
148 sta via_pcr
149 lda #$7f
150 sta via_ier
151 lda #$40
152 sta via_acr
153 lda #$c0
154 sta via_ier
155 lda #$10
156 sta via_t1ll
157 sta via_t1cl
158 lda #$27
159 sta via_t1lh
160 sta via_t1ch
161
162 forever_loop
163 jsr LoadData ; Load the main game (parameters are directly initialized in the loader variables at the end of the file)
164 jsr _LoaderApiJump ; Give control to the application and hope it knows what to do
165 jmp forever_loop
166
167
168 ; -------------------------------------------------------------------------------
169 ; Resident section
170 ; -------------------------------------------------------------------------------
171 ;
172 ; This section of the loader stays in memory at all time.
173 ; It contains all the code for loading, saving, as well as memory areas used by the
174 ; API to communicated between the main application and the loader.
175 ;
176 _LoaderResidentStart
177
178 ; X=File index
179 LoadData
180 ldy #0
181 sty __fetchByte+1
182
183 ; We have to start somewhere no matter what, compressed or not
184 sei
185
186 ; Make sure the microdisc IRQ is disabled
187 jsr WaitCompletion
188
189 lda #FDC_Flags_Mask ; Disable the FDC (Eprom select + FDC Interrupt request)
190 __fdc_flags_1
191 sta FDC_flags
192
193 ; Starting track
194 ldy #%00000000 ; Side 0
195 lda _LoaderApiFileStartTrack ; If the track id is larger than 128, it means it is on the other side of the floppy
196 bpl first_side
197 ; The file starts on the second side
198 ldy #FDC_Flag_DiscSide ; Side 1
199 and #%01111111 ; Mask out the extra bit
200 first_side
201 sty current_side
202 sta current_track
203
204 ; First sector
205 lda _LoaderApiFileStartSector
206 and #%01111111 ; Clear out the top bit (compressed flag)
207 sta current_sector
208
209 clc
210 lda _LoaderApiAddressLow
211 sta ptr_destination+0
212 adc _LoaderApiFileSizeLow
213 sta ptr_destination_end+0
214
215 lda _LoaderApiAddressHigh
216 sta ptr_destination+1
217 adc _LoaderApiFileSizeHigh
218 sta ptr_destination_end+1
219
220 ; Now at this stage we have to check if the data is compressed or not
221 lda _LoaderApiFileStartSector
222 bmi LoadCompressedData
223
224 LoadUncompressedData
225 ldy #0
226 read_sectors_loop
227 jsr GetNextByte ; Read from source stream
228 sta (ptr_destination),y
229
230 ; We increase the current destination pointer, by a given value, white checking if we reach the end of the buffer.
231 inc ptr_destination
232 bne skip_destination_inc1
233 inc ptr_destination+1
234 skip_destination_inc1
235
236 lda ptr_destination
237 cmp ptr_destination_end
238 lda ptr_destination+1
239 sbc ptr_destination_end+1
240 bcc read_sectors_loop
241 cli ; Data successfully loaded (we hope), so we restore the interrupts
242 rts
243
244 LoadCompressedData
245 cli
246
247 ; Initialise variables
248 ; We try to keep "y" null during all the code, so the block copy routine has to be sure that Y is null on exit
249 lda #1
250 sta mask_value
251
252 unpack_loop
253 ; Handle bit mask
254 lsr mask_value
255 bne end_reload_mask
256
257 jsr GetNextByte ; Read from source stream
258
259 ror
260 sta mask_value
261 end_reload_mask
262 bcc back_copy
263
264 write_byte
265 ; Copy one byte from the source stream
266 jsr GetNextByte ; Read from source stream
267 sta (ptr_destination),y
268
269 lda #1
270 sta nb_dst
271
272 _UnpackEndLoop
273 ; We increase the current destination pointer, by a given value, white checking if we reach the end of the buffer.
274 clc
275 lda ptr_destination
276 adc nb_dst
277 sta ptr_destination
278
279 bcc skip_destination_inc
280 inc ptr_destination+1
281 skip_destination_inc
282
283 cmp ptr_destination_end
284 lda ptr_destination+1
285 sbc ptr_destination_end+1
286 bcc unpack_loop
287 rts
288
289
290 back_copy
291 ;BreakPoint jmp BreakPoint
292 ; Copy a number of bytes from the already unpacked stream
293 ; Here we know that Y is null. So no need for clearing it: Just be sure it's still null at the end.
294 ; At this point, the source pointer points to a two byte value that actually contains a 4 bits counter, and a 12 bit offset to point back into the depacked stream.
295 ; The counter is in the 4 high order bits.
296 ;clc <== No need, since we access this routie from a BCC
297 jsr GetNextByte ; Read from source stream
298 adc #1
299 sta offset
300 jsr GetNextByte ; Read from source stream
301 tax
302 and #$0f
303 adc #0
304 sta offset+1
305
306 txa
307 lsr
308 lsr
309 lsr
310 lsr
311 clc
312 adc #3
313 sta nb_dst
314
315 sec
316 lda ptr_destination
317 sbc offset
318 sta ptr_source_back
319 lda ptr_destination+1
320 sbc offset+1
321 sta ptr_source_back+1
322
323 ; Beware, in that loop, the direction is important since RLE like depacking is done by recopying the
324 ; very same byte just copied... Do not make it a reverse loop to achieve some speed gain...
325 .(
326 copy_loop
327 lda (ptr_source_back),y ; Read from already unpacked stream
328 sta (ptr_destination),y ; Write to destination buffer
329 iny
330 cpy nb_dst
331 bne copy_loop
332 .)
333 ldy #0
334 beq _UnpackEndLoop
335 rts
336
337 GetNextByte
338 php
339 lda __fetchByte+1
340 bne __fetchByte
341 nop
342 nop
343 nop
344 nop
345 sei
346 jsr ReadNextSector
347 nop
348 nop
349 nop
350 nop
351 cli
352 ldx #0
353 ldy #0
354 __fetchByte
355 lda LOADER_SECTOR_BUFFER
356 inc __fetchByte+1
357 plp
358 rts
359
360
361
362 ReadNextSector
363 lda current_sector ; Check if we have reached the end of the track
364 cmp #FLOPPY_SECTOR_PER_TRACK+1
365 bne end_change_track
366
367 inc current_track ; Move to the next track
368 lda current_track
369 cmp #FLOPPY_TRACK_NUMBER
370 bne end_side_change
371
372 lda #0 ; Reset to the first track on the other side
373 sta current_track
374
375 __fdc_discside
376 lda #FDC_Flag_DiscSide
377 sta current_side
378 end_side_change
379
380 lda #1 ; Reset the sector position
381 sta current_sector
382 end_change_track
383
384 cli
385 jsr WaitCommand
386 sei
387
388 lda current_sector
389 __fdc_sector_1
390 .dsb ((FDC_sector_register&3)-((*+3)&3))&3,$ea
391 sta FDC_sector_register
392 inc current_sector
393
394 lda current_track ; Check if the drive is on the correct track
395 __fdc_track_1
396 .dsb ((FDC_track_register&3)-((*+3)&3))&3,$ea
397 cmp FDC_track_register
398 beq stay_on_the_track
399
400 __fdc_data_1
401 .dsb ((FDC_data&3)-((*+3)&3))&3,$ea
402 sta FDC_data ; Set the new track
403
404 lda #CMD_Seek
405 __fdc_command_1
406 .dsb ((FDC_command_register&3)-((*+3)&3))&3,$ea
407 sta FDC_command_register
408 jsr WaitCompletion
409 stay_on_the_track
410
411 lda #FDC_Flags_Mask ; Apply the side selection mask
412 ora current_side
413 __fdc_flags_2
414 sta FDC_flags
415
416 __fdc_readsector
417 lda #CMD_ReadSector
418 __fdc_command_2
419 .dsb ((FDC_command_register&3)-((*+3)&3))&3,$ea
420 sta FDC_command_register
421
422 jsr WaitCommand
423
424 ; Read the sector data
425 ldx #0
426 loop_read_sector
427 __fdc_drq_1
428 .dsb ((FDC_drq&3)-((*+3)&3))&3,$ea
429 lda FDC_drq
430 bmi loop_read_sector
431 __fdc_data_2
432 .dsb ((FDC_data&3)-((*+3)&3))&3,$ea
433 lda FDC_data
434 sta LOADER_SECTOR_BUFFER,x ; Store the byte in the sector buffer
435 inx
436 bne loop_read_sector
437
438 __fdc_status_1
439 .dsb ((FDC_status_register&3)-((*+3)&3))&3,$ea
440 lda FDC_status_register
441 and #$1C
442
443 jsr WaitCompletion
444 cli
445 rts
446
447 WaitCommand
448 ldx #wait_status_floppy
449 waitcommand
450 nop
451 nop
452 dex
453 bne waitcommand
454 rts
455
456 WaitCompletion
457 txa
458 pha
459
460 php
461 sei
462 nop
463 nop
464 nop
465
466 ldx #4
467 r_wait_completion
468 dex
469 bne r_wait_completion
470 plp
471
472 r2_wait_completion
473 __fdc_status_2
474 .dsb ((FDC_status_register&3)-((*+3)&3))&3,$ea
475 lda FDC_status_register
476 lsr
477 bcs r2_wait_completion
478
479 pla
480 tax
481 rts
482
483
484 IrqHandler
485 bit $304
486 IrqDoNothing
487 rti
488
489 _EndLoaderCode
490
491 ;
492 ; This is free memory that can be used, when it reaches zero then the loader start address should be changed
493 ;
494
495 .dsb $FFEF - _EndLoaderCode
496
497 _Vectors
498
499 #if ( _Vectors <> $FFEF )
500 #error - Vector address is incorrect, loader will crash
501 #else
502
503 ;
504 ; Here are the functions that the user can call from his own application
505 ;
506 _LoaderApiFileStartSector .byt LOADER_INTRO_PROGRAM_SECTOR ; $FFEF
507 _LoaderApiFileStartTrack .byt LOADER_INTRO_PROGRAM_TRACK ; $FFF0
508
509 _LoaderApiFileSize
510 _LoaderApiFileSizeLow .byt <LOADER_INTRO_PROGRAM_SIZE ; $FFF1
511 _LoaderApiFileSizeHigh .byt >LOADER_INTRO_PROGRAM_SIZE ; $FFF2
512
513 ; Could have a JMP here as well to launch the loaded program
514 _LoaderApiJump .byt OPCODE_JMP ; $FFF3
515 _LoaderApiAddress
516 _LoaderApiAddressLow .byt <LOADER_INTRO_PROGRAM_ADDRESS ; $FFF4
517 _LoaderApiAddressHigh .byt >LOADER_INTRO_PROGRAM_ADDRESS ; $FFF5
518 _LoaderXxxxxx_available .byt 0 ; $FFF6
519 _LoaderApiLoadFile .byt OPCODE_JMP,<LoadData,>LoadData ; $FFF7-$FFF9
520
521 ;
522 ; These three HAVE to be at these precise adresses, they map to hardware registers
523 ;
524 _VectorNMI .word IrqDoNothing ; $FFFA-$FFFB - NMI Vector (Usually points to $0247)
525 _VectorReset .word IrqDoNothing ; $FFFC-$FFFD - RESET Vector (Usually points to $F88F)
526 _VectorIRQ .word IrqHandler ; $FFFE-$FFFF - IRQ Vector (Normally points to $0244)
527
528 #echo Remaining space in the loader code:
529 #print (_Vectors - _EndLoaderCode)
530
531 #endif
532
533 ; End of the loader - Nothing should come after because it's out of the addressable memory range :)

  ViewVC Help
Powered by ViewVC 1.1.26