1;       CRT0 stub for the Old School Computer Architecture (FLOS)
2;
3;       Stefano Bodrato - Jul. 2011
4;
5;
6;       EXTRA OPTIONS:
7;
8;		At C source level:
9;       #pragma output osca_bank=(0..14) set the memory bank for locations > 32768 before loading program
10;		#pragma output REGISTER_SP=<value> put the stack in a differen place, i.e. 32767
11;		#pragma output nostreams       - No stdio disc files
12;		#pragma output noredir         - do not insert the file redirection option while parsing the
13;		                                 command line arguments (useless if "nostreams" is set)
14;		#pragma output osca_notimer    - Save very few bytes and excludes the clock handling,
15;                                        thus disabling those functions connected to time.h
16;		#pragma output osca_restoretxt - works only with FLOS > v547, restores the text mode on program exit
17;
18;       At compile time:
19;		-zorg=<location> parameter permits to specify the program position
20;
21;	$Id: osca_crt0.asm,v 1.38 2016-07-15 21:38:08 dom Exp $
22;
23
24
25                MODULE  osca_crt0
26
27;
28; Initially include the zcc_opt.def file to find out lots of lovely
29; information about what we should do..
30;
31
32		defc    crt0 = 1
33                INCLUDE "zcc_opt.def"
34
35; No matter what set up we have, main is always, always external to
36; this file
37
38        EXTERN    _main
39
40
41;
42; Some variables which are needed for both app and basic startup
43;
44
45        PUBLIC    cleanup
46        PUBLIC    l_dcal
47
48
49; FLOS system variables
50        PUBLIC	sector_lba0		; keep this byte order
51        PUBLIC	sector_lba1
52        PUBLIC	sector_lba2
53        PUBLIC	sector_lba3
54
55        PUBLIC	a_store1
56        PUBLIC	bc_store1
57        PUBLIC	de_store1
58        PUBLIC	hl_store1
59        PUBLIC	a_store2
60        PUBLIC	bc_store2
61        PUBLIC	de_store2
62        PUBLIC	hl_store2
63        PUBLIC	storeix
64        PUBLIC	storeiy
65        PUBLIC	storesp
66        PUBLIC	storepc
67        PUBLIC	storef
68        PUBLIC	store_registers
69        PUBLIC	com_start_addr
70
71        PUBLIC	cursor_y		;keep this byte order
72        PUBLIC	cursor_x		;(allows read as word with y=LSB)
73
74        PUBLIC	current_scancode
75        PUBLIC	current_asciicode
76
77
78;--------
79; OSCA / FLOS specific definitions
80;--------
81
82        INCLUDE "flos.def"
83        INCLUDE "osca.def"
84
85
86; Now, getting to the real stuff now!
87
88
89;--------
90; Set an origin for the application (-zorg=) default to $5000
91;--------
92
93IF      !DEFINED_CRT_ORG_CODE
94	defc    CRT_ORG_CODE  = $5000
95ENDIF
96
97        defc    CONSOLE_COLUMNS = 40
98        defc    CONSOLE_ROWS = 25
99
100	defc	TAR__no_ansifont = 1
101        defc    TAR__clib_exit_stack_size = 32
102        defc    TAR__register_sp = 65536 - 6
103	defc	__CPU_CLOCK = 4000000
104        INCLUDE "crt/classic/crt_rules.inc"
105
106
107IF ((CRT_ORG_CODE = $5000) | (!DEFINED_osca_bank))
108       org	CRT_ORG_CODE
109ELSE
110	; optional Program Location File Header
111	org	CRT_ORG_CODE
112	defb	$ed
113	defb	$00
114	jr	start
115	defw	CRT_ORG_CODE
116    IF DEFINED_osca_bank
117	defb	osca_bank
118    ELSE
119	defb    0
120    ENDIF
121	defb	$00 ; control byte: 1=truncate basing on next 3 bytes
122	;defw	0   ; Load length 15:0 only needed if truncate flag is set
123	;defb	0	; Load length ..bits 23:16, only needed if truncate flag is set
124ENDIF
125
126start:
127        di
128
129	ld	(cmdline+1),hl
130;	ld	b,h
131;	ld	c,l
132
133        ld      (start1+1),sp
134        INCLUDE "crt/classic/crt_init_sp.asm"
135        INCLUDE "crt/classic/crt_init_atexit.asm"
136;	push	bc
137	call	crt0_init_bss
138;	pop	bc
139        ld      (exitsp),sp
140;       push	bc  ; keep ptr to arg list
141
142; Optional definition for auto MALLOC init
143; it assumes we have free space between the end of
144; the compiled program and the stack pointer
145IF DEFINED_USING_amalloc
146	INCLUDE "crt/classic/crt_init_amalloc.asm"
147ENDIF
148
149IF (!DEFINED_osca_notimer)
150
151        ld  hl,(FLOS_irq_vector)            		; The label "irq_vector" = $A01 (contained in equates file)
152        ld  (original_irq_vector),hl   		; Store the original FLOS vecotr for restoration later.
153        ld  hl,my_custom_irq_handler
154        ld  (FLOS_irq_vector),hl
155
156        ld  a,@10000111                		; Enable keyboard, mouse and timer interrupts
157        out  (sys_irq_enable),a
158
159        ld a,250
160        neg
161        out (sys_timer),a
162
163        ld  a,@00000100
164        out  (sys_clear_irq_flags),a           ; Clear the timer IRQ flag
165ELSE
166	ld	b,255
167.v_srand_loop
168	ld	hl,FLOSvarsaddr
169	add	(hl)
170	ld	(FRAMES),a
171	inc hl
172	djnz v_srand_loop
173ENDIF
174        ei
175
176	; Push pointers to argv[n] onto the stack now
177	; We must start from the end
178	;pop	hl	; command line back again
179cmdline:
180	ld		hl,0	; SMC
181
182	ld	bc,0
183	ld	a,(hl)
184	and	a
185	jr	z,argv_done
186	dec	hl
187find_end:
188	inc	hl
189	inc	c
190	ld	a,(hl)
191	and	a
192	jr	nz,find_end
193	dec	hl
194
195	INCLUDE "crt/classic/crt_command_line.asm"
196
197        push    hl      ;argv
198        push    bc      ;argc
199
200	call    _main		;Call user code
201
202	pop	bc	;kill argv
203	pop	bc	;kill argc
204
205cleanup:
206;
207;       Deallocate memory which has been allocated here!
208;
209        push	hl		;save exit value
210        call    crt0_exit
211
212	; kjt_flos_display restores the text mode but makes the screen flicker
213	; if it is in text mode already
214	;
215IF (DEFINED_osca_restoretxt)
216        call	$10c4 ; kjt_flos_display (added in v547)
217ENDIF
218IF (!DEFINED_osca_notimer)
219        di
220        ld		hl,(original_irq_vector)
221        ld		(FLOS_irq_vector),hl
222        ld		a,@10000011                     ; Enable keyboard and mouse interrupts only
223        out		(sys_irq_enable),a
224        ei
225ENDIF
226        pop	hl	; restore exit value
227start1:
228        ld	sp,0
229        xor	a
230        or	h	; ATM we are not mamaging the 'spawn' exception
231        jr	nz,cmdok
232        ld	l,a
233cmdok:
234        ld	a,l	; return code (lowest byte only)
235        and	a	; set Z flag to set the eventual error condition
236        ;xor a ; (set A and flags for RESULT=OK)
237        ret
238
239l_dcal:
240        jp      (hl)
241
242IF (!DEFINED_osca_notimer)
243; ----------------------------------
244; Custom Interrupt handlers
245; ----------------------------------
246my_custom_irq_handler:
247        push af
248        in  a,(sys_irq_ps2_flags)
249        bit  0,a
250        call nz,kjt_keyboard_irq_code      ; Kernal keyboard irq handler
251        bit  1,a
252        call nz,kjt_mouse_irq_code         ; Kernal mouse irq handler
253        bit  2,a
254        call nz,my_timer_irq_code          ; User's timer irq handler
255        pop af
256        ei
257        reti
258
259my_timer_irq_code:
260        push af                            ; (do whatever, push/pop registers!)
261        push hl
262
263;        ld hl,(frames_pre)
264;        inc (hl)
265;        ld a,(hl)
266;        bit 4,a
267;        jr nz,timer_irq_count_done
268
269        ld hl,(FRAMES)
270        inc hl
271        ld (FRAMES),hl
272        ;;ld	(palette),hl		; testing purposes
273        ld a,h
274        or l
275        jr nz,timer_irq_count_done
276        ld hl,(FRAMES+2)
277        inc hl
278        ld (FRAMES+2),hl
279
280timer_irq_count_done:
281        ld  a,@00000100
282        out  (sys_clear_irq_flags),a           ; Clear the timer IRQ flag
283
284        pop  hl
285        pop  af
286        ret
287ENDIF
288
289	SECTION		bss_crt
290
291        PUBLIC	FRAMES
292original_irq_vector:
293	defw 0
294
295FRAMES:
296	defw 0
297	defw 0
298
299
300
301end:
302         defb  0
303
304
305;--------------------------------------------------------------------------------------------
306;
307; OS_variables location as defined in system_equates.asm
308; FLOSv582 sets it to $B00, hopefully it won't change much
309; but we keep the option for making it dynamic
310;
311;--------------------------------------------------------------------------------------------
312
313IF !DEFINED_FLOSvarsaddr
314      defc FLOSvarsaddr = $B00
315ENDIF
316
317;--------------------------------------------------------------------------------------------
318
319DEFVARS FLOSvarsaddr
320{
321
322sector_lba0	ds.b 1		; keep this byte order
323sector_lba1	ds.b 1
324sector_lba2	ds.b 1
325sector_lba3	ds.b 1
326
327a_store1		ds.b 1
328bc_store1		ds.b 2
329de_store1		ds.b 2
330hl_store1		ds.b 2
331a_store2		ds.b 1
332bc_store2		ds.b 2
333de_store2		ds.b 2
334hl_store2		ds.b 2
335storeix		ds.b 2
336storeiy		ds.b 2
337storesp		ds.b 2
338storepc		ds.b 2
339storef	  	ds.b 1
340store_registers	ds.b 1
341com_start_addr	ds.w 1
342
343cursor_y		ds.b 1		;keep this byte order
344cursor_x		ds.b 1		;(allows read as word with y=LSB)
345
346current_scancode	ds.b 1
347current_asciicode	ds.b 1
348
349; The other variable positions depend on the FLOS version
350; ..
351}
352
353;--------------------------------------------------------------------------------------------
354
355        INCLUDE "crt/classic/crt_runtime_selection.asm"
356	INCLUDE "crt/classic/crt_section.asm"
357
358	SECTION  code_crt_init
359	ld	hl,$2000
360	ld	(base_graphics),hl
361
362
363        SECTION  rodata_clib
364IF !DEFINED_noredir
365IF CRT_ENABLE_STDIO = 1
366redir_fopen_flag:               defb    'w',0
367redir_fopen_flagr:              defb    'r',0
368ENDIF
369ENDIF
370
371
372
373; SD CARD interface
374IF DEFINED_NEED_SDCARD
375	SECTION bss_crt
376	PUBLIC card_select
377	PUBLIC sd_card_info
378
379	PUBLIC sector_buffer_loc
380
381; Keep the following 2 bytes in the right order (1-card_select, 2-sd_card_info) !!!
382card_select:		defb    0    ; Currently selected MMC/SD slot
383sd_card_info:		defb    0    ; Card type flags..
384
385sector_buffer_loc:	defw	0
386sector_buffer:		defs	513
387
388	SECTION code_crt_init
389	ld	hl,sector_buffer
390	ld	(sector_buffer_loc),hl
391
392ENDIF
393
394