File: atbasic.s

package info (click to toggle)
atari800 5.2.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 7,196 kB
  • sloc: ansic: 86,829; asm: 18,694; sh: 3,173; cpp: 2,798; java: 2,453; xml: 957; makefile: 727; perl: 334; pascal: 178
file content (767 lines) | stat: -rw-r--r-- 17,983 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
; Altirra BASIC
; Copyright (C) 2014-2016 Avery Lee, All Rights Reserved.
;
; Copying and distribution of this file, with or without modification,
; are permitted in any medium without royalty provided the copyright
; notice and this notice are preserved.  This file is offered as-is,
; without any warranty.

		opt		m-

		icl		'system.inc'
		icl		'tokens.inc'

;===========================================================================
.macro _MSG_BANNER
		dta		c'Altirra 8K BASIC 1.58'
.endm

;===========================================================================
; Zero page variables
;
; We try to be sort of compatible with Atari BASIC here, supporting all
; public variables and trying to support some unofficial usage as well.
;
; Test cases:
;	QUADRATO.BAS
;	- Uses $B0-B3 from USR() routine

		org		$0080
		opt		o-
argstk	equ		*
lomem	dta		a(0)		;$0080 (compat) from lomem; argument/operator stack
vntp	dta		a(0)		;$0082 (compat - loaded) variable name table pointer
vntd	dta		a(0)		;$0084 (compat - loaded) variable name table end
vvtp	dta		a(0)		;$0086 (compat - loaded) variable value table pointer
stmtab	dta		a(0)		;$0088 (compat - loaded) statement table pointer
stmcur	dta		a(0)		;$008A (compat - loaded) current statement pointer
starp	dta		a(0)		;$008C (compat - loaded) string and array table
runstk	dta		a(0)		;$008E (compat) runtime stack pointer
memtop2	dta		a(0)		;$0090 (compat) top of BASIC memory

exLineOffset	dta		0		;offset within current line being executed
exLineOffsetNxt	dta		0		;offset of next statement
exLineEnd		dta		0		;offset of end of current line
exTrapLine		dta		a(0)	;TRAP line
exFloatStk		dta		0		;bit 7 set if stack is floating (line numbers)
parPtrSav:					;[6 bytes] VNTD/VVTP/STMTAB save area for parser rollback
opsp		dta		0		;operand stack pointer offset
argsp		dta		0		;argument stack pointer offset
expCommas	dta		0		;expression evaluator comma count
expFCommas	dta		0
expAsnCtx	dta		0		;flag - set if this is an assignment context for arrays
expType		dta		0		;bit 7 = 0 for numeric, 1 for string
varptr		dta		a(0)	;pointer to current variable
lvarptr		dta		a(0)	;lvar pointer for array assignment
parptr		dta		a(0)	;parsing state machine pointer
parout		dta		0		;parsing output idx
expCurPrec	dta		0		;expression evaluator current operator precedence
iocbexec	dta		0		;current immediate/deferred mode IOCB
iocbidx		dta		0		;current IOCB*16
iocbidx2	dta		0		;current IOCB (used to distinguish #0 and #16)
iterPtr		dta		a(0)	;pointer used for sequential name table indexing
ioPrintCol	dta		0		;IO: current PRINT column
ioTermSave	dta		0		;IO: String terminator byte save location
ioTermOff	dta		0		;IO: String terminator byte offset
argstk2		dta		a(0)	;Evaluator: Second argument stack pointer
dataLnEnd	dta		0		;current DATA statement line end
pmgbase		dta		0
pmgmode		dta		0
ioTermFlag	dta		0

		.if grColor!=$c8
		.error "Graphics color is at ",grColor," but must be at $C8 for PEEK(200) to work (see Space Station Multiplication.bas)"
		.endif

		.if *>$b7
		.error "Zero page overflow: ",*
		.endif

			org		$b7
dataln		dta		a(0)	;(compat - Mapping the Atari / ANALOG verifier) current DATA statement line


stopln	= $ba				;(compat - Atari BASIC manual): line number of error
		; $bb
		
;--------------------------------------------------------------------------
; $BC-BF are reserved as scratch space for use by the currently executing
; statement or by the parser. They must not be used by functions or library
; code.
;
			org		$bc
stScratch	dta		0
stScratch2	dta		0
stScratch3	dta		0
stScratch4	dta		0

printDngl	= stScratch		;set if the print statement is 'dangling' - no follow EOL
parStrType	= prefr0		;parsing string type: set if string exp, clear if numeric
parStBegin	= stScratch2	;parsing offset of statement begin (0 if none)

;--------------------------------------------------------------------------
; $C0-C1 are reserved as scratch space for use by the currently executing
; function.
;
funScratch1	= $c0
funScratch2	= $c1
;--------------------------------------------------------------------------
errno	= $c2
errsave	= $c3				;(compat - Atari BASIC manual): error number

			org		$c4
dataptr		dta		a(0)	;current DATA statement pointer
dataoff		dta		0		;current DATA statement offset
			dta		0		;(unused)
grColor		dta		0		;graphics color (must be at $C8 for Space Station Multiplication)
ptabw		dta		0		;(compat - Atari BASIC manual): tab width

.if ptabw != $C9
			.error	"PTABW is wrong"
.endif

.if * > $CB
.error "$CB-D1 are reserved"
.endif

;--------------------------------------------------------------------------
; $CB-D1 are reserved for use by annoying people that read Mapping The
; Atari.
;--------------------------------------------------------------------------
; Floating-point library vars
;
; $D2-D3 is used as an extension prefix to FR0; $D4-FF are used by the FP
; library, but can be reused outside of it.
;
prefr0	= fr0-2
a0		= fr0				;temporary pointer 0
a1		= fr0+2				;temporary pointer 1
a2		= fr0+4				;temporary pointer 2
a3		= fr0+6				;temporary pointer 3
a4		= fr0+8				;temporary pointer 4
a5		= fr0+10			;temporary pointer 5

degflg	= $fb				;(compat) degree/radian flag: 0 for radians, 6 for degrees

lbuff	equ		$0580

.macro _STATIC_ASSERT
		.if :1
		.else
		.error ":2"
		.endif
.endm

.macro _PAGE_CHECK
		.if [:1^*]&$ff00
		.error "Page boundary crossed between ",:1," and ",*
		.endif
.endm

;==========================================================================
; EXE loader start
;
		.if CART==0

		org		$3000
		opt		o+
		
;==========================================================================
; Preloader
;
; The preloader executes before the main load.

.proc __preloader
		;check if BASIC is on
		jsr		__testROM
		beq		basic_ok
		
		;try to turn basic off
		lda		#0
		sta		basicf
		lda		portb
		ora		#2
		sta		portb

		;check again if BASIC is on
		jsr		__testROM
		beq		basic_ok

		;print failure
		mwa		#msg_romconflict_begin icbal
		mwa		#msg_romconflict_end-msg_romconflict_begin icbll
		mva		#CIOCmdPutChars iccmd
		ldx		#0
		jsr		ciov

		lda		#$ff
		cmp:req	ch
		sta		ch

		;exit
		jmp		(dosvec)
		
basic_ok:
		;print loading banner and continue disk load
		mwa		#msg_loading_begin icbal
		mwa		#msg_loading_end-msg_loading_begin icbll
		mva		#CIOCmdPutChars iccmd
		ldx		#0
		jmp		ciov

msg_loading_begin:
		dta		'Loading Altirra BASIC...'
msg_loading_end:

msg_romconflict_begin:
		dta		$9B
		dta		'Cannot load Altirra BASIC: another',$9B
		dta		'ROM is already present at $A000.',$9B
		dta		$9B
		dta		'If you are running under SpartaDOS X,',$9B
		dta		'use the X command to run ATBasic.',$9B
		dta		$9B
		dta		'Press a key',$9B
msg_romconflict_end:
.endp

;--------------------------------------------------------------------------
; Exit:
;	Z=0: Not writable
;	Z=1: Writable
;
.proc __testROM
		lda		$a000
		tax
		eor		#$ff
		sta		$a000
		cmp		$a000
		stx		$a000
		rts		
.endp

;--------------------------------------------------------------------------

		ini		__preloader

;--------------------------------------------------------------------------
.proc __loader
		;reset RAMTOP if it is above $A000
		lda		#$a0
		cmp		ramtop
		bcs		ramtop_ok

adjust_ramtop:
		sta		ramtop
		
		;reinitialize GR.0 screen if needed (XEP80 doesn't)
		lda		sdmctl
		and		#$20
		beq		dma_off
		
		jsr		wait_vbl

		ldx		#0
		stx		dmactl
		stx		sdmctl
		lda		#4
		cmp:rcc	vcount
		mva		#CIOCmdClose iccmd
		jsr		ciov

		mva		#CIOCmdOpen iccmd
		mwa		#editor icbal
		mva		#$0c icax1
		mva		#$00 icax2
		ldx		#0
		jsr		ciov

		;Wait for a VBLANK to ensure that the screen has taken place;
		;we don't just use RTCLOK because we need to ensure that stage
		;2 VBLANK has been run, not just stage 1.
		jsr		wait_vbl
dma_off:
ramtop_ok:

		;Check if we might have the OS-A or OS-B screen editor. The OS-A/B
		;screen editor has a nasty bug of clearing up to one page more than
		;it should on a screen clear, which will trash the beginning of our
		;soft-loaded BASIC interpreter. In that case, we need to drop RAMTOP
		;by another 4K to compensate. 4K is a lot, but is necessary since
		;the screen editor does not align playfields properly otherwise.
		
		;The first check we do is to see if the memory limit is already $9F00
		;or lower; if so, we don't have a problem.
		lda		ramtop
		cmp		#$A0
		bcc		editor_ok

		;The first check we do is to see if the put char routine for E: is
		;that of OS-A/B. If it isn't, then either we aren't running on OS-A/B,
		;or E: has been replaced. Either way, we're fine.
		lda		icptl
		cmp		#$A3
		bne		editor_ok
		lda		#$F6
		cmp		icptl+1
		bne		editor_ok

		;Okay, we might have OS-A/B. However, there's a chance that someone
		;preserved that entry point but fixed the editor (hah). So, let's do
		;a test: put a test byte at $A000 and clear the screen. If it gets
		;wiped, we have a problem.
		sta		$A000

		ldx		#0
		stx		icbll
		stx		icblh
		mva		#CIOCmdPutChars iccmd
		lda		#$7d
		jsr		ciov

		lda		$A000
		cmp		#$FC
		beq		editor_ok

		;Whoops... the test byte was overwritten. Lower RAMTOP from $A0 to
		;$90 and reinitialize E:.
		lda		#$90
		bne		adjust_ramtop

editor_ok:
		;reset RUNAD to $A000 so we can be re-invoked
		mwa		#$a000 runad

		;move $3800-57FF to $A000-BFFF
		mva		#$38 fr0+1
		mva		#$a0 fr1+1
		ldy		#0
		sty		fr0
		sty		fr1
		ldx		#$20
copy_loop:
		mva:rne	(fr0),y (fr1),y+
		inc		fr0+1
		inc		fr1+1
		dex
		bne		copy_loop

		;check if there is a command line to process
		ldy		#0
		sty		iocbidx				;!! - needed since we will be skipping it
		lda		(dosvec),y
		cmp		#$4c
		bne		no_cmdline
		ldy		#3
		lda		(dosvec),y
		cmp		#$4c
		beq		have_cmdline
no_cmdline:
		lda		#0
		jmp		no_filename

have_cmdline:
		;skip spaces
		ldy		#10
		lda		(dosvec),y
		clc
		adc		#63
		tay
space_loop:
		lda		(dosvec),y
		cmp		#$9b
		beq		no_filename
		iny
		cmp		#' '
		beq		space_loop

		;stash filename base offset
		dey
		sty		fr0+3

		;check if the first character is other than D and there is a colon
		;afterward -- if so, we should skip DOS's parser and use it straight
		;as it may be a CIO filename that DOS would munge
		cmp		#'D'
		beq		possibly_dos_file
cio_file:
		;copy filename to LBUFF
		ldx		#0
cio_copy_loop:
		lda		(dosvec),y
		sta		lbuff,x
		inx
		iny
		cmp		#$9b
		bne		cio_copy_loop

		;stash length
		stx		fr0+2

		tya
		jmp		have_filename_nz

possibly_dos_file:
		;scan for colon
colon_loop:
		lda		(dosvec),y
		iny
		cmp		#':'
		beq		cio_file
		cmp		#$9b
		bne		colon_loop

		;okay, assume it's a DOS file - clear the CIO filename flag
		lda		#0
		sta		fr0+2
		
		;try to parse out a filename
		ldy		fr0+3
		sec
		sbc		#63
		ldy		#10
		sta		(dosvec),y

		ldy		#4
		mva		(dosvec),y fr0
		iny
		mva		(dosvec),y fr0+1
		jsr		jump_fr0
		
no_filename:
have_filename_nz:
		;save off filename flag
		php

		;cold boot ATBasic
		ldx		#0
		stx		iocbidx
		stx		iocbexec
		inx
		stx		errno

		;print startup banner
		mwa		#msg_banner_begin icbal
		mwa		#msg_banner_end-msg_banner_begin icbll
		mva		#CIOCmdPutChars iccmd
		ldx		#0
		jsr		ciov

		jsr		_stNew.reset_entry
		jsr		ExecReset

		;read filename flag
		plp
		bne		explicit_fn

		;no filename... try loading implicit file
		ldx		#$70
		stx		iocbidx
		mwa		#default_fn_start icbal+$70
		mwa		#default_fn_end-default_fn_start icbll+$70
		mva		#CIOCmdOpen iccmd+$70
		mva		#$04 icax1+$70
		jsr		ciov
		bmi		load_failed

		;load and run
		lsr		stLoadRun._loadflg
		jmp		stLoadRun.with_open_iocb

load_failed:
		;failed... undo the EOL with an up arrow so the prompt is in the right place
		mva		#0 iocbidx
		lda		#$1c
		jsr		putchar

		;close IOCB and jump to prompt
		ldx		#$70
		mva		#CIOCmdClose iccmd+$70
		jsr		ciov
		jmp		immediateModeReset

explicit_fn:
		;move filename to line buffer
		ldy		#33
		ldx		#0
		stx		fr0+3

		;check if filename is already there
		lda		fr0+2
		bne		fncopy_skip
fncopy_loop:
		lda		(dosvec),y
		sta		lbuff,x
		cmp		#$9b
		beq		fncopy_exit
		iny
		inx
		bne		fncopy_loop
fncopy_exit:
		;finish length
		stx		fr0+2

fncopy_skip:
		;set string pointer
		mwa		#lbuff fr0

		;set up for RUN statement
		jsr		IoPutNewline
		lsr		stLoadRun._loadflg
		ldx		#$70
		stx		iocbidx
		jmp		stLoadRun.loader_entry

wait_vbl:
		sei
		mwa		#1 cdtmv3
		cli
		lda:rne	cdtmv4
		rts

jump_fr0:
		jmp		(fr0)

editor:
		dta		c'E',$9B

default_fn_start:
		dta		'D:AUTORUN.BAS',$9B
default_fn_end:

msg_banner_begin:
		dta		$9c				;delete loading line
		_MSG_BANNER
		dta		$9b
msg_banner_end:
.endp

		opt		h-
		dta		a($ffff),a($3800),a($57ff)

		.endif
		
;==========================================================================
; Cartridge start
;
		opt		h-
		org		$a000
		opt		o+f+

;==========================================================================
; Entry point
;
; This is totally skipped in the EXE version, where we reuse the space for
; a reload-E: stub when returning to DOS.
;
		.if CART==0
msg_base = *+13
ReturnToDOS:
		ldx		#0
		jsr		IoCloseX
		mva		#$c0 ramtop
		sta		icax2
		lda		#$0c
		ldy		#<devname_e
		jsr		IoOpenStockDeviceX			;!! this overwrites $BC20+
		jmp		(dosvec)

		:13 dta 0

		.else
main:
		;check if this is a warm start
		ldx		warmst
		bmi		immediateModeReset
				
		;print banner
		sec
		rol		ioTermFlag
		jsr		IoPrintMessageIOCB0		;!! - X=0
		jmp		stNew

;==========================================================================
; Message base
;
msg_base:
msg_banner:
		_MSG_BANNER
		dta		0
		.endif

		.if		msg_base != $A00D
		.error	"msg_base misaligned: ",*
		.endif

		.if		* != $A023
		.error	"msg_ready misaligned: ",*
		.endif
		org		$A023

msg_ready:
		dta		$9B,c'Ready',$9B,0

msg_stopped:
		dta		$9B,c"Stopped",0

msg_error:
		dta		$9B
msg_error2:
		dta		c"Error-   ",0

msg_atline:
		dta		c" at line ",0
msg_end:

		_STATIC_ASSERT (msg_end - msg_base) <= $100

;==========================================================================
immediateModeReset:
		jsr		ExecReset
immediateMode:
		;use IOCB #0 (E:) for commands
		ldx		#0
		stx		iocbexec
.proc execLoop
		;display prompt
		ldx		#msg_ready-msg_base
		jsr		IoPrintMessageIOCB0

loop2:	
		;reset stack
		ldx		#$ff
		txs

		;read read pointer
		inx
		stx		cix

		;reset errno
		inx
		stx		errno
	
		;read line
		ldx		iocbexec
		jsr		IoReadLineX			;also sets iocbidx for error handling
		beq		eof
		
		;float the stack if it isn't already
		jsr		ExecFloatStack

		;##TRACE "Parsing immediate mode line: [%.*s]" dw(icbll) lbuff
		jsr		parseLine
		bcc		loop2		

		;execute immediate mode line
		jmp		execDirect
		
eof:
		;close IOCB #7
		jsr		IoSetupIOCB7		;closes #7 as side effect
		
		;restart in immediate mode with IOCB 0
		jmp		immediateMode
.endp
 
;==========================================================================

		icl		'parserbytecode.s'
		icl		'parser.s'
		icl		'exec.s'
		icl		'data.s'
		icl		'statements.s'
		icl		'evaluator.s'
		icl		'functions.s'
		icl		'variables.s'
		icl		'math.s'
		icl		'io.s'
		icl		'memory.s'
		icl		'list.s'
		icl		'error.s'
		icl		'util.s'


;==========================================================================

pmg_dmactl_tab:					;3 bytes ($1c 0c 00)
		dta		$1c,$0c
empty_program:					;4 bytes ($00 00 80 03)
		dta		$00
pmgmode_tab:					;2 bytes ($00 80)
		dta		$00,$80
		dta		$03

;==========================================================================

const_table = $bffa - 4 - 6*9 - 6 - 7

		.echo	"Main program ends at ",*," (",[((((*-$a000)*100/8192)/10)*16+(((*-$a000)*100)/8192)%10)],"% full) (", const_table-*," bytes free)"

		org		const_table
		.echo	"Constant table begins at ",*
		.pages 1

devname_c:
		dta		'C'
devname_s:
		dta		'S'
devname_e:
		dta		'E'
devname_p:
		dta		'P'
devpath_d1all:
		dta		'D:*.*',$9B

		;The Maclaurin expansion for sin(x) is as follows:
		;
		; sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - x^11/11!...
		;
		;We modify it this way:
		;
		; let y = x / pi2 (for x in [0, pi], pi2 = pi/2
		; sin(x) = y*[pi2 - y^2*pi2^3/3! + y^4*pi2^5/5! - y^6*pi2^7/7! + y^8*pi2*9/9! - y^10*pi2^11/11!...]
		;
		; let z = y^2
		; sin(x) = y*[pi2 - z*pi2^3/3! + z^2*pi2^5/5! - z^3*pi2^7/7! + z^4*pi2*9/9! - z^5*pi2^11/11!...]
		;
fpconst_sin:
		dta		$BD,$03,$43,$18,$69,$61		;-0.00 00 03 43 18 69 61 07114469471
		dta		$3E,$01,$60,$25,$47,$91		; 0.00 01 60 25 47 91 80067132008
		dta		$BE,$46,$81,$65,$78,$84		;-0.00 46 81 65 78 83 6641486819
		dta		$3F,$07,$96,$92,$60,$37		; 0.07 96 92 60 37 48579552158
		dta		$BF,$64,$59,$64,$09,$56		;-0.64 59 64 09 55 8200198258
angle_conv_tab:
fpconst_pi2:
		dta		$40,$01,$57,$07,$96,$33		; 1.57 07 96 32 67682236008 (also last sin coefficient)
		dta		$40,$90,$00,$00,$00			; 90 (!! - last byte shared with next table!)
hvstick_table:
		dta		$00,$FF,$01,$00

fp_180_div_pi:
		.fl		57.295779513082

const_one:
		dta		$40,$01
pmg_move_mask_tab:
		dta		$00,$00,$00,$00,$fc,$f3,$cf,$3f

		.endpg

		_STATIC_ASSERT *=$bffa
		
;==========================================================================
		
		.echo	"Program ends at ",*," (",[((((*-$a000)*100/8192)/10)*16+(((*-$a000)*100)/8192)%10)],"% full)"

		org		$bffa
		dta		a($a000)		;boot vector
		dta		$00				;do not init
		dta		$05				;boot disk/tape, boot cart
		dta		a(ExNop)		;init vector (no-op)

		.if CART==0
		opt		f-h+
		run		__loader
		.endif
		
		end