OpenCores
URL https://opencores.org/ocsvn/rtf65002/rtf65002/trunk

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [bootrom.asm] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 robfinch
; ============================================================================
2
;        __
3
;   \\__/ o\    (C) 2013  Robert Finch, Stratford
4
;    \  __ /    All rights reserved.
5
;     \/_//     robfinch@opencores.org
6
;       ||
7
;
8
;
9
; This source file is free software: you can redistribute it and/or modify
10
; it under the terms of the GNU Lesser General Public License as published
11
; by the Free Software Foundation, either version 3 of the License, or
12
; (at your option) any later version.
13
;
14
; This source file is distributed in the hope that it will be useful,
15
; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
; GNU General Public License for more details.
18
;
19
; You should have received a copy of the GNU General Public License
20
; along with this program.  If not, see .
21
;
22
; ============================================================================
23
;
24
CR      EQU     0x0D            ;ASCII equates
25
LF      EQU     0x0A
26
TAB     EQU     0x09
27
CTRLC   EQU     0x03
28
CTRLH   EQU     0x08
29
CTRLI   EQU     0x09
30
CTRLJ   EQU     0x0A
31
CTRLK   EQU     0x0B
32
CTRLM   EQU 0x0D
33
CTRLS   EQU     0x13
34
CTRLX   EQU     0x18
35
XON             EQU     0x11
36
XOFF    EQU     0x13
37
 
38 26 robfinch
; error codes
39
E_Ok            =               0x00
40
E_Arg           =               0x01
41
E_BadMbx        =               0x04
42
E_QueFull       =               0x05
43
E_NoThread      =               0x06
44
E_NotAlloc      =               0x09
45
E_NoMsg         =               0x0b
46
E_Timeout       =               0x10
47
E_BadAlarm      =               0x11
48
E_NotOwner      =               0x12
49
; resource errors
50
E_NoMoreMbx     =               0x40
51
E_NoMoreMsgBlks =       0x41
52
E_NoMoreAlarmBlks       =0x44
53
E_NoMoreTCBs    =       0x45
54
 
55
; task status
56
TS_NONE     =0
57
TS_TIMEOUT      =1
58
TS_WAITMSG      =2
59 28 robfinch
TS_PREEMPT      =4
60 26 robfinch
TS_RUNNING      =8
61
TS_READY        =16
62 31 robfinch
TS_SLEEP        =32
63 26 robfinch
 
64 31 robfinch
MAX_TASKNO      = 255
65 26 robfinch
 
66 31 robfinch
DIRENT_NAME             =0x00   ; file name
67
DIRENT_EXT              =0x1C   ; file name extension
68
DIRENT_ATTR             =0x20   ; attributes
69
DIRENT_DATETIME =0x28
70
DIRENT_CLUSTER  =0x30   ; starting cluster of file
71
DIRENT_SIZE             =0x34   ; file size (6 bytes)
72
 
73
; One FCB is allocated and filled out for each file that is open.
74
;
75
nFCBs   = 128
76
FCB_DE_NAME             =0x00
77
FCB_DE_EXT              =0x1C
78
FCB_DE_ATTR             =0x20
79
FCB_DE_DATETIME =0x28
80
FCB_DE_CLUSTER  =0x30   ; starting cluster of file
81
FCB_DE_SIZE             =0x34   ; 6 byte file size
82
FCB_DIR_SECTOR  =0x40   ; LBA directory sector this is from
83
FCB_DIR_ENT             =0x44   ; offset in sector for dir entry
84
FCB_LDRV                =0x48   ; logical drive this is on
85
FCB_MODE                =0x49   ; 0 read, 1=modify
86
FCB_NUSERS              =0x4A   ; number of users of this file
87
FCB_FMOD                =0x4B   ; flag: this file was modified
88
FCB_RESV                =0x4C   ; padding out to 80 bytes
89
FCB_SIZE                =0x50
90
 
91
FUB_JOB         =0x00   ; User's job umber
92
FUB_iFCB        =0x02   ; FCB number for this file
93
FUB_CrntLFA     =0x04   ; six byte current logical file address
94
FUB_pBuf        =0x0C   ; pointer to buffer if in stream mode
95
FUB_sBuf        =0x10   ; size of buffer for stream file
96
FUB_LFABuf      =0x14   ; S-First LFA in Clstr Buffer
97
FUB_LFACluster  =0x18   ; LFA of cluster
98
FUB_Clstr       = 0x20          ; The last cluster read
99
FUB_fModified   = 0x24  ; data in buffer was modified
100
FUB_fStream             = 0x25  ; non-zero for stream mode
101
FUB_PAD         =0x26
102
FUB_SIZE        =0x30
103
 
104
; Boot sector info (62 byte structure) */
105
BSI_JMP         = 0x00
106
BSI_OEMName     = 0x03
107
BSI_bps         = 0x0B
108
BSI_SecPerCluster       = 0x0D
109
BSI_ResSectors  = 0x0E
110
BSI_FATS        = 0x10
111
BSI_RootDirEnts = 0x11
112
BSI_Sectors     = 0x13
113
BSI_Media       = 0x15
114
BSI_SecPerFAT   = 0x16
115
BSI_SecPerTrack = 0x18
116
BSI_Heads       = 0x1A
117
BSI_HiddenSecs  = 0x1C
118
BSI_HugeSecs    = 0x1E
119
 
120
BSI_DriveNum    = 0x24
121
BSI_Rsvd1               = 0x25
122
BSI_BootSig             = 0x26
123
BSI_VolID               = 0x27
124
BSI_VolLabel    = 0x2B
125
BSI_FileSysType = 0x36
126
 
127
 
128
MEM_CHK         =0
129
MEM_FLAG        =1
130
MEM_PREV        =2
131
MEM_NEXT        =3
132
 
133 26 robfinch
; message queuing strategy
134
MQS_UNLIMITED   =0      ; unlimited queue size
135
MQS_NEWEST              =1      ; buffer queue size newest messages
136
MQS_OLDEST              =2      ; buffer queue size oldest messages
137
 
138 31 robfinch
LEDS            EQU             0xFFDC0600
139 11 robfinch
TEXTSCR         EQU             0xFFD00000
140
COLORSCR        EQU             0xFFD10000
141
TEXTREG         EQU             0xFFDA0000
142
TEXT_COLS       EQU             0x0
143
TEXT_ROWS       EQU             0x1
144
TEXT_CURPOS     EQU             11
145
KEYBD           EQU             0xFFDC0000
146
KEYBDCLR        EQU             0xFFDC0001
147 15 robfinch
PIC                     EQU             0xFFDC0FF0
148
PIC_IE          EQU             0xFFDC0FF1
149 31 robfinch
PIC_ES          EQU             0xFFDC0FF4
150
PIC_RSTE        EQU             0xFFDC0FF5
151 26 robfinch
TASK_SELECT     EQU             0xFFDD0008
152
RQ_SEMA         EQU             0xFFDB0000
153
TO_SEMA         EQU             0xFFDB0010
154
SERIAL_SEMA     EQU             0xFFDB0020
155
KEYBD_SEMA      EQU             0xFFDB0030
156
IOF_LIST_SEMA   EQU     0xFFDB0040
157
MBX_SEMA        EQU             0xFFDB0050
158 31 robfinch
MEM_SEMA        EQU             0xFFDB0060
159 11 robfinch
 
160
SPIMASTER       EQU             0xFFDC0500
161
SPI_MASTER_VERSION_REG  EQU     0x00
162
SPI_MASTER_CONTROL_REG  EQU     0x01
163
SPI_TRANS_TYPE_REG      EQU             0x02
164
SPI_TRANS_CTRL_REG      EQU             0x03
165
SPI_TRANS_STATUS_REG    EQU     0x04
166
SPI_TRANS_ERROR_REG             EQU     0x05
167
SPI_DIRECT_ACCESS_DATA_REG              EQU     0x06
168
SPI_SD_SECT_7_0_REG             EQU     0x07
169
SPI_SD_SECT_15_8_REG    EQU     0x08
170
SPI_SD_SECT_23_16_REG   EQU     0x09
171
SPI_SD_SECT_31_24_REG   EQU     0x0a
172
SPI_RX_FIFO_DATA_REG    EQU     0x10
173
SPI_RX_FIFO_DATA_COUNT_MSB      EQU     0x12
174
SPI_RX_FIFO_DATA_COUNT_LSB  EQU 0x13
175
SPI_RX_FIFO_CTRL_REG            EQU     0x14
176
SPI_TX_FIFO_DATA_REG    EQU     0x20
177
SPI_TX_FIFO_CTRL_REG    EQU     0x24
178
SPI_RESP_BYTE1                  EQU     0x30
179
SPI_RESP_BYTE2                  EQU     0x31
180
SPI_RESP_BYTE3                  EQU     0x32
181
SPI_RESP_BYTE4                  EQU     0x33
182
SPI_INIT_SD                     EQU             0x01
183
SPI_TRANS_START         EQU             0x01
184
SPI_TRANS_BUSY          EQU             0x01
185
SPI_INIT_NO_ERROR       EQU             0x00
186
SPI_READ_NO_ERROR       EQU             0x00
187 15 robfinch
SPI_WRITE_NO_ERROR      EQU             0x00
188 11 robfinch
RW_READ_SD_BLOCK        EQU             0x02
189
RW_WRITE_SD_BLOCK       EQU             0x03
190
 
191 26 robfinch
UART            EQU             0xFFDC0A00
192
UART_LS         EQU             0xFFDC0A01
193
UART_MS         EQU             0xFFDC0A02
194
UART_IS         EQU             0xFFDC0A03
195
UART_IE         EQU             0xFFDC0A04
196
UART_MC         EQU             0xFFDC0A06
197
UART_CM1        EQU             0xFFDC0A09
198
UART_CM2        EQU             0xFFDC0A0A
199
UART_CM3        EQU             0xFFDC0A0B
200
txempty         EQU             0x40
201
rxfull          EQU             0x01
202
 
203
CONFIGREC       EQU             0xFFDCFFF0
204
CR_CLOCK        EQU             0xFFDCFFF4
205
GACCEL          EQU             0xFFDAE000
206 28 robfinch
AC97            EQU             0xFFDC1000
207
PSG                     EQU             0xFFD50000
208
PSGFREQ0        EQU             0xFFD50000
209
PSGPW0          EQU             0xFFD50001
210
PSGCTRL0        EQU             0xFFD50002
211
PSGADSR0        EQU             0xFFD50003
212 26 robfinch
 
213
ETHMAC          EQU             0xFFDC2000
214
ETH_MODER               EQU             0x00
215
ETH_INT_SOURCE  EQU             0x01
216
ETH_INT_MASK    EQU             0x02
217
ETH_IPGT                EQU             0x03
218
ETH_IPGR1               EQU             0x04
219
ETH_IPGR2               EQU             0x05
220
ETH_PACKETLEN   EQU             0x06
221
ETH_COLLCONF    EQU             0x07
222
ETH_TX_BD_NUM   EQU             0x08
223
ETH_CTRLMODER   EQU             0x09
224
ETH_MIIMODER    EQU             0x0A
225
ETH_MIICOMMAND  EQU             0x0B
226
ETH_MIIADDRESS  EQU             0x0C
227
ETH_MIITX_DATA  EQU             0x0D
228
ETH_MIIRX_DATA  EQU             0x0E
229
ETH_MIISTATUS   EQU             0x0F
230
ETH_MAC_ADDR0   EQU             0x10
231
ETH_MAC_ADDR1   EQU             0x11
232
ETH_HASH0_ADDR  EQU             0x12
233
ETH_HASH1_ADDR  EQU             0x13
234
ETH_TXCTRL              EQU             0x14
235
 
236
SPRITEREGS      EQU             0xFFDAD000
237
SPRRAM          EQU             0xFFD80000
238
 
239
THRD_AREA       EQU             0x04000000      ; threading area 0x04000000-0x40FFFFF
240
BITMAPSCR       EQU             0x04100000
241
SECTOR_BUF      EQU             0x05FBEC00
242
BIOS_STACKS     EQU             0x05FC0000      ; room for 256 1kW stacks
243
BIOS_SCREENS    EQU     0x05C00000      ; 0x05C00000 to 0x05DFFFFF
244
 
245 15 robfinch
BYTE_SECTOR_BUF EQU     SECTOR_BUF<<2
246 26 robfinch
PROG_LOAD_AREA  EQU             0x4180000<<2
247 11 robfinch
 
248 31 robfinch
FCBs                    EQU             0x5F40000       ; room for 128 FCB's
249 28 robfinch
 
250 31 robfinch
FATOFFS                 EQU             0x5F50000       ; offset into FAT on card
251
FATBUF                  EQU             0x5F60000
252
DIRBUF                  EQU             0x5F70000
253 26 robfinch
eth_rx_buffer   EQU             0x5F80000
254
eth_tx_buffer   EQU             0x5F84000
255 11 robfinch
 
256 26 robfinch
; Mailboxes, room for 2048
257
MBX_LINK        EQU             0x05F90000
258
MBX_TQ_HEAD     EQU             0x05F90800
259
MBX_TQ_TAIL     EQU             0x05F91000
260
MBX_MQ_HEAD     EQU             0x05F91800
261
MBX_MQ_TAIL     EQU             0x05F92000
262
MBX_TQ_COUNT    EQU     0x05F92800
263
MBX_MQ_SIZE     EQU             0x05F93000
264
MBX_MQ_COUNT    EQU     0x05F93800
265
MBX_MQ_MISSED   EQU     0x05F94000
266
MBX_OWNER               EQU     0x05F94800
267
MBX_MQ_STRATEGY EQU     0x05F95000
268
MBX_RESV                EQU     0x05F95800
269 11 robfinch
 
270 26 robfinch
; Messages, room for 8kW (8,192) messages
271
MSG_LINK        EQU             0x05FA0000
272
MSG_D1          EQU             0x05FA2000
273
MSG_D2          EQU             0x05FA4000
274
MSG_TYPE        EQU             0x05FA6000
275
 
276
; Task control blocks, room for 256 tasks
277
TCB_NxtRdy              EQU             0x05FBE100      ; next task on ready / timeout list
278
TCB_PrvRdy              EQU             0x05FBE200      ; previous task on ready / timeout list
279
TCB_NxtTCB              EQU             0x05FBE300
280
TCB_Timeout             EQU             0x05FBE400
281
TCB_Priority    EQU             0x05FBE500
282
TCB_MSGPTR_D1   EQU             0x05FBE600
283
TCB_MSGPTR_D2   EQU             0x05FBE700
284
TCB_hJCB                EQU             0x05FBE800
285
TCB_Status              EQU             0x05FBE900
286
TCB_CursorRow   EQU             0x05FBD100
287
TCB_CursorCol   EQU             0x05FBD200
288
TCB_hWaitMbx    EQU             0x05FBD300      ; handle of mailbox task is waiting at
289
TCB_mbq_next    EQU             0x05FBD400      ; mailbox queue next
290
TCB_mbq_prev    EQU             0x05FBD500      ; mailbox queue previous
291 28 robfinch
TCB_iof_next    EQU             0x05FBD600
292
TCB_iof_prev    EQU             0x05FBD700
293
TCB_SP8Save             EQU             0x05FBD800      ; TCB_SP8Save area
294
TCB_SPSave              EQU             0x05FBD900      ; TCB_SPSave area
295 31 robfinch
TCB_ABS8Save    EQU             0x05FBDA00
296 26 robfinch
 
297
KeybdHead       EQU             0x05FBEA00
298
KeybdTail       EQU             0x05FBEB00
299
KeybdEcho       EQU             0x05FBEC00
300
KeybdBad        EQU             0x05FBED00
301
KeybdAck        EQU             0x05FBEE00
302
KeybdLocks      EQU             0x05FBEF00
303
KeybdBuffer     EQU             0x05FBF000      ; buffer is 16 chars
304
 
305 31 robfinch
HeapStart       EQU             0x04200000
306
HeapEnd         EQU             0x05AFFFFF
307
 
308 28 robfinch
; Bitmap of tasks requesting the I/O focus
309
;
310
IOFocusTbl      EQU             0x05FBD000
311 26 robfinch
 
312 28 robfinch
; EhBASIC vars:
313 15 robfinch
;
314 26 robfinch
NmiBase         EQU             0xDC
315
IrqBase         EQU             0xDF
316
 
317 28 robfinch
; BIOS vars at the top of the 8kB scratch memory
318
;
319
; TinyBasic AREA = 0xF00 to 0xF7F
320 26 robfinch
 
321 28 robfinch
HeadRdy0        EQU             0xF80
322 26 robfinch
HeadRdy1        EQU             HeadRdy0+1
323
HeadRdy2        EQU             HeadRdy1+1
324
HeadRdy3        EQU             HeadRdy2+1
325
HeadRdy4        EQU             HeadRdy3+1
326
TailRdy0        EQU             HeadRdy4+1
327
TailRdy1        EQU             TailRdy0+1
328
TailRdy2        EQU             TailRdy1+1
329
TailRdy3        EQU             TailRdy2+1
330
TailRdy4        EQU             TailRdy3+1
331
FreeTCB         EQU             TailRdy4+1
332
TimeoutList     EQU             FreeTCB+1
333
RunningTCB              EQU             TimeoutList+1
334
FreeMbx         EQU             RunningTCB + 1
335
nMailbox        EQU             FreeMbx + 1
336
FreeMsg         EQU             nMailbox + 1
337
nMsgBlk         EQU             FreeMsg + 1
338
 
339 28 robfinch
; The IO focus list is a doubly linked list formed into a ring.
340
;
341
IOFocusNdx      EQU             nMsgBlk + 1
342 26 robfinch
 
343 28 robfinch
IrqSource       EQU             0xF98
344 15 robfinch
 
345 28 robfinch
JMPTMP          EQU             0xFA0
346
SP8Save         EQU             0xFAE
347
SRSave          EQU             0xFAF
348
R1Save          EQU             0xFB0
349
R2Save          EQU             0xFB1
350
R3Save          EQU             0xFB2
351
R4Save          EQU             0xFB3
352
R5Save          EQU             0xFB4
353
R6Save          EQU             0xFB5
354
R7Save          EQU             0xFB6
355
R8Save          EQU             0xFB7
356
R9Save          EQU             0xFB8
357
R10Save         EQU             0xFB9
358
R11Save         EQU             0xFBA
359
R12Save         EQU             0xFBB
360
R13Save         EQU             0xFBC
361
R14Save         EQU             0xFBD
362
R15Save         EQU             0xFBE
363
SPSave          EQU             0xFBF
364 15 robfinch
 
365 28 robfinch
CharColor       EQU             0xFC0
366
ScreenColor     EQU             0xFC1
367
CursorRow       EQU             0xFC2
368
CursorCol       EQU             0xFC3
369
CursorFlash     EQU             0xFC4
370
Milliseconds    EQU             0xFC5
371
IRQFlag         EQU             0xFC6
372
RdyQueTick      EQU             0xFC7
373
eth_unique_id   EQU             0xFC8
374
LineColor       EQU             0xFC9
375 31 robfinch
QIndex          EQU             0xFCA
376 28 robfinch
 
377 26 robfinch
Uart_rxfifo             EQU             0x05FBC000
378 28 robfinch
Uart_rxhead             EQU             0xFD0
379
Uart_rxtail             EQU             0xFD1
380
Uart_ms                 EQU             0xFD2
381
Uart_rxrts              EQU             0xFD3
382
Uart_rxdtr              EQU             0xFD4
383
Uart_rxxon              EQU             0xFD5
384
Uart_rxflow             EQU             0xFD6
385
Uart_fon                EQU             0xFD7
386
Uart_foff               EQU             0xFD8
387
Uart_txrts              EQU             0xFD9
388
Uart_txdtr              EQU             0xFDA
389
Uart_txxon              EQU             0xFDB
390
Uart_txxonoff   EQU             0xFDC
391 15 robfinch
 
392 28 robfinch
startSector     EQU             0xFF0
393 15 robfinch
 
394
 
395 11 robfinch
        cpu             rtf65002
396
        code
397 15 robfinch
 
398 26 robfinch
message "jump table"
399 15 robfinch
        ; jump table of popular BIOS routines
400 31 robfinch
        org             $FFFF8000
401 15 robfinch
        dw      DisplayChar
402
        dw      KeybdCheckForKeyDirect
403
        dw      KeybdGetCharDirect
404 26 robfinch
        dw      KeybdGetChar
405
        dw      KeybdCheckForKey
406
        dw      RequestIOFocus
407
        dw      ReleaseIOFocus
408
        dw      ClearScreen
409
        dw      HomeCursor
410
        dw      ExitTask
411
        dw      SetKeyboardEcho
412 28 robfinch
        dw      Sleep
413 31 robfinch
        dw      do_load
414
        dw      do_save
415 15 robfinch
 
416 31 robfinch
        org             $FFFF8400               ; leave room for 256 vectors
417 26 robfinch
message "cold start point"
418 15 robfinch
KeybdRST
419 11 robfinch
start
420
        sei                                             ; disable interrupts
421
        cld                                             ; disable decimal mode
422 31 robfinch
        lda             #1
423
        sta             LEDS
424 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer top of memory
425 11 robfinch
        txs
426 31 robfinch
        trs             r0,abs8                 ; set 8 bit mode absolute address offset
427 15 robfinch
 
428 31 robfinch
        jsr             MemInit                 ; Initialize the heap
429
 
430
        lda             #2
431
        sta             LEDS
432
 
433 15 robfinch
        ; setup interrupt vectors
434 26 robfinch
        ldx             #$05FB0001              ; interrupt vector table from $5FB0000 to $5FB01FF
435 18 robfinch
                                                        ; also sets nmoi policy (native mode on interrupt)
436 15 robfinch
        trs             r2,vbr
437 18 robfinch
        dex
438 15 robfinch
        lda             #brk_rout
439
        sta             (x)
440
        lda             #slp_rout
441
        sta             1,x
442
        lda             #KeybdRST
443
        sta             448+1,x
444
        lda             #p1000Hz
445
        sta             448+2,x
446
        lda             #p100Hz
447
        sta             448+3,x
448
        lda             #KeybdIRQ
449
        sta             448+15,x
450 26 robfinch
        lda             #SerialIRQ
451
        sta             448+8,x
452 31 robfinch
        lda             #InvalidOpIRQ
453
        sta             495,x
454 26 robfinch
        lda             #bus_err_rout
455
        sta             508,x
456
        sta             509,x
457 15 robfinch
 
458 31 robfinch
        lda             #3
459
        sta             LEDS
460
 
461
        ; stay in native mode in case emulation is not supported.
462
        ldx             #$1FF                   ; set 8 bit stack pointer
463
        trs             r2,sp8
464 26 robfinch
 
465
        ldx             #0
466
        stz             IrqBase                 ; support for EhBASIC's interrupt mechanism
467
        stz             NmiBase
468 31 robfinch
 
469 26 robfinch
        lda             #-1
470
        sta             TimeoutList             ; no entries in timeout list
471 31 robfinch
        sta             HeadRdy0                ; task zero (the BIOS task) is always present
472 26 robfinch
        sta             HeadRdy1
473
        sta             HeadRdy2
474
        sta             HeadRdy3
475
        sta             HeadRdy4
476 31 robfinch
        sta             TailRdy0
477 26 robfinch
        sta             TailRdy1
478
        sta             TailRdy2
479
        sta             TailRdy3
480
        sta             TailRdy4
481
 
482 31 robfinch
 
483 26 robfinch
        ; Initialize IO Focus List
484
        ;
485 31 robfinch
        ldx             #1
486 26 robfinch
st5:
487 28 robfinch
        stz             IOFocusTbl,x
488 26 robfinch
        inx
489
        cpx             #8
490
        bne             st5
491
 
492 31 robfinch
        ldx             #1
493 28 robfinch
        lda             #-1
494
st9:
495
        sta             TCB_iof_next,x
496
        sta             TCB_iof_prev,x
497
        inx
498
        cpx             #256
499
        bne             st9
500
 
501 26 robfinch
        ; Initialize free message list
502
        lda             #8192
503
        sta             nMsgBlk
504
        stz             FreeMsg
505
        ldx             #0
506
        lda             #1
507
st4:
508
        sta             MSG_LINK,x
509
        ina
510
        inx
511
        cpx             #8192
512
        bne             st4
513
        lda             #-1
514
        sta             MBX_LINK+8191
515
 
516
        ; Initialize free mailbox list
517
        lda             #2048
518
        sta             nMailbox
519
 
520
        stz             FreeMbx
521
        ldx             #0
522
        lda             #1
523
st3:
524
        sta             MBX_LINK,x
525
        ina
526
        inx
527
        cpx             #2048
528
        bne             st3
529
        lda             #-1
530
        sta             MBX_LINK+2047
531
 
532
        ; Initialize the FreeTCB list
533
        lda             #1                              ; the next available TCB
534
        sta             FreeTCB
535
        ldx             #1
536
        lda             #2
537
st2:
538
        sta             TCB_NxtTCB,x
539
        ina
540
        inx
541
        cpx             #256
542
        bne             st2
543
        lda             #-1
544
        sta             TCB_NxtTCB+255
545 31 robfinch
        lda             #4
546
        sta             LEDS
547 26 robfinch
 
548 31 robfinch
        ; Manually setup the BIOS task
549
        lda             #-1
550
        stz             RunningTCB              ; BIOS is task #0
551
        sta             TCB_NxtRdy              ; manually build the ready list
552
        sta             TCB_PrvRdy
553
        stz             HeadRdy0                ; insert at priority 4
554
        stz             TailRdy0
555
        stz             TCB_iof_next    ; manually build the IO focus list
556
        stz             TCB_iof_prev
557
        stz             IOFocusNdx              ; task #0 has the focus
558 26 robfinch
        lda             #1
559 31 robfinch
        sta             IOFocusTbl              ; set the task#0 request bit
560
        lda             #0
561
        sta             TCB_Priority
562
        lda             #TS_RUNNING|TS_READY
563
        sta             TCB_Status
564
        stz             TCB_CursorRow
565
        stz             TCB_CursorCol
566
 
567
        lda             #1
568 26 robfinch
        sta             MBX_SEMA
569
        sta             IOF_LIST_SEMA
570
        sta             RQ_SEMA                 ; set ready queue semaphore
571
        sta             TO_SEMA                 ; set timeout list semaphore
572 31 robfinch
 
573 11 robfinch
        lda             #$CE                    ; CE =blue on blue FB = grey on grey
574
        sta             ScreenColor
575
        sta             CharColor
576 26 robfinch
        sta             CursorFlash
577 11 robfinch
        jsr             ClearScreen
578 15 robfinch
        jsr             ClearBmpScreen
579 31 robfinch
        lda             #4
580
        ldx             #0
581
        ldy             #IdleTask
582
        jsr             StartTask
583
        jsr             PICInit
584
        lda             CONFIGREC               ; do we have a serial port ?
585
        bit             #32
586
        beq             st7
587
        ; 19200 * 16
588
        ;-------------
589
        ; 25MHz / 2^32
590
        lda             #$03254E6E              ; constant for 19,200 baud at 25MHz
591
        jsr             SerialInit
592
st7:
593
        lda             #5
594
        sta             LEDS
595 28 robfinch
        lda             CONFIGREC               ; do we have sprites ?
596
        bit             #1
597
        beq             st8
598 26 robfinch
        lda             #$3FFF                  ; turn on sprites
599
        sta             SPRITEREGS+120
600
        jsr             RandomizeSprram
601 28 robfinch
st8:
602 31 robfinch
        ; Enable interrupts.
603
        ; Keyboard initialization must take place after interrupts are
604
        ; enabled.
605
        cli
606
        lda             #14
607
        sta             LEDS
608 15 robfinch
        jsr             KeybdInit
609
        lda             #1
610
        sta             KeybdEcho
611 31 robfinch
        lda             #6
612
        sta             LEDS
613
 
614 28 robfinch
        ; The following must be after interrupts are enabled.
615 31 robfinch
        lda             #9
616
        sta             LEDS
617
        jsr             HomeCursor
618
        lda             #msgStart
619
        jsr             DisplayStringB
620
        jsr             ReportMemFree
621
        lda             #10
622
        sta             LEDS
623
 
624 28 robfinch
        ; The AC97 setup uses the millisecond counter and the
625
        ; keyboard.
626
        lda             CONFIGREC               ; do we have a sound generator ?
627
        bit             #4
628
        beq             st6
629
        jsr             SetupAC97
630 31 robfinch
        lda             #2
631
        ldx             #0
632
        ldy             #Beep
633
        jsr             StartTask
634 28 robfinch
st6:
635 31 robfinch
        lda             #11
636
        sta             LEDS
637 15 robfinch
        jmp             Monitor
638
st1
639
        jsr             KeybdGetCharDirect
640
        bra             st1
641 11 robfinch
        stp
642
        bra             start
643
 
644
msgStart
645
        db              "RTF65002 system starting.",$0d,$0a,00
646
 
647 15 robfinch
;----------------------------------------------------------
648
; Initialize programmable interrupt controller (PIC)
649
;  0 = nmi (parity error)
650
;  1 = keyboard reset
651 31 robfinch
;  2 = 1000Hz pulse
652 15 robfinch
;  3 = 100Hz pulse (cursor flash)
653
;  4 = ethmac
654
;  8 = uart
655
; 13 = raster interrupt
656
; 15 = keyboard char
657
;----------------------------------------------------------
658 26 robfinch
message "PICInit"
659 15 robfinch
PICInit:
660 31 robfinch
        ;
661
        lda             #$000C                  ; clock pulses are edge sensitive
662
        sta             PIC_ES
663
        lda             #$000F                  ; enable nmi,kbd_rst
664 15 robfinch
        ; A10F enable serial IRQ
665
        sta             PIC_IE
666
PICret:
667
        rts
668
 
669 11 robfinch
;------------------------------------------------------------------------------
670 26 robfinch
;------------------------------------------------------------------------------
671
message "DumpTaskList"
672
DumpTaskList:
673
        pha
674
        phx
675
        phy
676
        push    r4
677
        lda             #msgTaskList
678
        jsr             DisplayStringB
679
        ldy             #0
680
        php
681
        sei
682
dtl2:
683
        lda             HeadRdy0,y
684
        ld              r4,r1
685
        bmi             dtl1
686
dtl3:
687
        ldx             #3
688
        tya
689
        jsr             PRTNUM
690
        lda             #' '
691
        jsr             DisplayChar
692
        ld              r1,r4
693
        ldx             #3
694
        jsr             PRTNUM
695
        lda             #' '
696
        jsr             DisplayChar
697
        jsr             DisplayChar
698
        jsr             DisplayChar
699
        ld              r1,r4
700
        lda             TCB_Status,r1
701
        jsr             DisplayByte
702
        lda             #' '
703
        jsr             DisplayChar
704
        ldx             #3
705
        lda             TCB_PrvRdy,r4
706
        jsr             PRTNUM
707
        lda             #' '
708
        jsr             DisplayChar
709
        ldx             #3
710
        lda             TCB_NxtRdy,r4
711
        jsr             PRTNUM
712
        lda             #' '
713
        jsr             DisplayChar
714
        lda             TCB_Timeout,r4
715
        jsr             DisplayWord
716
        jsr             CRLF
717
        ld              r4,TCB_NxtRdy,r4
718
        bpl             dtl3
719
dtl1:
720
        iny
721
        cpy             #5
722
        bne             dtl2
723
        plp
724
        pop             r4
725
        ply
726
        plx
727
        pla
728
        rts
729
 
730
msgTaskList:
731
        db      CR,LF,"Pri Task Stat Prv Nxt Timeout",CR,LF,0
732
 
733
;------------------------------------------------------------------------------
734 28 robfinch
;------------------------------------------------------------------------------
735
message "DumpIOFocusList"
736
DumpIOFocusList:
737
        pha
738
        phx
739
        phy
740
        php
741
        sei
742
        lda             #msgIOFocusList
743
        jsr             DisplayStringB
744
        lda             IOFocusNdx
745
diofl2:
746
        bmi             diofl1
747
        tay
748
        ldx             #3
749
        jsr             PRTNUM
750
        lda             #' '
751
        jsr             DisplayChar
752
        lda             TCB_iof_prev,y
753
        ldx             #3
754
        jsr             PRTNUM
755
        lda             #' '
756
        jsr             DisplayChar
757
        lda             TCB_iof_next,y
758
        ldx             #3
759
        jsr             PRTNUM
760
        jsr             CRLF
761
        lda             TCB_iof_next,y
762
        cmp             IOFocusNdx
763
        bne             diofl2
764
 
765
diofl1:
766
        plp
767
        ply
768
        plx
769
        pla
770
        rts
771
 
772
msgIOFocusList:
773
        db      CR,LF,"Task Prv Nxt",CR,LF,0
774 31 robfinch
 
775
RunningTCBErr:
776
        lda             #$FF
777
        sta             LEDS
778
        lda             #msgRunningTCB
779
        jsr             DisplayStringB
780
rtcberr1:
781
        jsr             KeybdGetChar
782
        cmp             #-1
783
        beq             rtcberr1
784
        jmp             start
785
 
786
msgRunningTCB:
787
        db      CR,LF,"RunningTCB is bad.",CR,LF,0
788
 
789 28 robfinch
;------------------------------------------------------------------------------
790 26 robfinch
; IdleTask is a low priority task that is always running. It runs when there
791
; is nothing else to run.
792
;------------------------------------------------------------------------------
793
IdleTask:
794
        inc             TEXTSCR+167             ; increment IDLE active flag
795
        cli                                             ; enable interrupts
796
        wai                                             ; wait for one to happen
797
        bra             IdleTask
798
 
799
;------------------------------------------------------------------------------
800
; r1 = task priority
801
; r2 = start flags
802
; r3 = start address
803
;------------------------------------------------------------------------------
804
message "StartTask"
805
StartTask:
806
        pha
807
        phx
808
        phy
809
        push    r4
810
        push    r5
811
        push    r6
812
        push    r7
813
        push    r8
814
        tsr             sp,r4                           ; save off current stack pointer
815
        ld              r6,r1                           ; r6 = task priority
816
        ld              r8,r2
817
 
818
        ; get a free TCB
819
        ;
820 31 robfinch
        php
821 26 robfinch
        sei
822
        lda             FreeTCB                         ; get free tcb list pointer
823
        bmi             stask1
824
        tax
825
        lda             TCB_NxtTCB,x
826
        sta             FreeTCB                         ; update the FreeTCB list pointer
827 31 robfinch
        plp
828 26 robfinch
        txa
829
 
830
        ; setup the stack for the task
831
        ld              r7,r2
832
        asl             r2,r2,#10                       ; 1kW stack per task
833
        add             r2,r2,#BIOS_STACKS+0x3ff        ; add in stack base
834
        txs
835
        ldx             #$FF
836
        stx             TCB_SP8Save,r7
837
        st              r6,TCB_Priority,r7
838
        stz             TCB_Status,r7
839
        stz             TCB_Timeout,r7
840 31 robfinch
        ; setup virtual video for the task
841
        stz             TCB_CursorRow,r7
842
        stz             TCB_CursorCol,r7
843 26 robfinch
 
844
        ; setup the initial stack image for the task
845
        ; Cause a return to the ExitTask routine when the task does a
846
        ; final rts.
847
        ; fake an IRQ call by stacking the return address and processor
848
        ; flags on the stack
849
        ldx             #ExitTask                       ; save the address of the task exit routine
850
        phx
851
        phy                                                     ; save start address on stack
852
        push    r8                                      ; save processor status reg on stack
853
 
854
        ; now fake pushing the register set onto the stack. Registers start up
855
        ; in an undefined state.
856
        sub             sp,#15                          ; 15 registers
857
        tsx
858
        stx             TCB_SPSave,r7
859
 
860
        ; now restore the current stack pointer
861
        trs             r4,sp
862
 
863
        ; Insert the task into the ready list
864
        jsr             AddTaskToReadyList
865
stask2:
866
        pop             r8
867
        pop             r7
868
        pop             r6
869
        pop             r5
870
        pop             r4
871
        ply
872
        plx
873
        pla
874
        rts
875
stask1:
876 31 robfinch
        plp
877 26 robfinch
        lda             #msgNoTCBs
878
        jsr             DisplayStringB
879
        bra             stask2
880
 
881
msgNoTCBs:
882
        db              "No more task control blocks available.",CR,LF,0
883
 
884
;------------------------------------------------------------------------------
885
; This routine is called when the task exits with an rts instruction. OR
886 28 robfinch
; it may be invoked with a JMP ExitTask. In either case the task must be
887
; running so it can't be on the timeout list.
888 26 robfinch
;------------------------------------------------------------------------------
889
message "ExitTask"
890
ExitTask:
891
        sei
892
        ; release any aquired resources
893
        ; - mailboxes
894
        ; - messages
895
        lda             RunningTCB
896 31 robfinch
        bmi             RunningTCBErr
897 26 robfinch
        jsr             RemoveTaskFromReadyList
898
        stz             TCB_Status,r1                           ; set task status to TS_NONE
899 28 robfinch
        jsr             ReleaseIOFocus
900
        ldx             FreeTCB                                         ; add the task control block to the free list
901 26 robfinch
        stx             TCB_NxtTCB,r1
902
        sta             FreeTCB
903
        jmp             SelectTaskToRun
904
 
905
;------------------------------------------------------------------------------
906
; AddTaskToReadyList
907
; This subroutine is called from the timer ISR so it must be relatively
908
; fast.
909
; Parameters:
910 31 robfinch
;       r1 = task number
911
; Returns:
912
;       none
913 26 robfinch
;------------------------------------------------------------------------------
914
message "AddTaskToReadyList"
915
AddTaskToReadyList:
916 31 robfinch
        php
917 28 robfinch
        pha
918 26 robfinch
        phx
919
        phy
920
        sei
921 31 robfinch
        ldy             TCB_Priority,r1
922 26 robfinch
        ldx             TCB_Status,r1   ; set the task status to ready
923
        or              r2,r2,#TS_READY
924
        stx             TCB_Status,r1
925
        ldx     TailRdy0,y              ; insert the task at the list tail
926 28 robfinch
        bmi             arl1                    ; if no tail, then either the list is screwed up, or no tasks are on it.
927
        sta             TCB_NxtRdy,x    ; add as next ready on tail
928
arl4:
929
        stx             TCB_PrvRdy,r1   ; the old tail is the previous task on the list now.
930
        sta             TailRdy0,y              ; update with new tail
931 26 robfinch
        ldx             #-1
932 28 robfinch
        stx             TCB_NxtRdy,r1   ; There is no next ready task to the tail.
933 26 robfinch
        ldx             HeadRdy0,y              ; check if the head of the ready list needs to be updated
934
        bpl             arl3
935 28 robfinch
        sta             HeadRdy0,y              ; Update the head of the ready list.
936
        ldx             #-1                             ; There is no previous task at the head.
937 26 robfinch
        stx             TCB_PrvRdy,r1
938
arl3:
939
        ply
940
        plx
941 28 robfinch
        pla
942 31 robfinch
        plp
943 26 robfinch
        rts
944 28 robfinch
        ; Here the tail of the ready list needed to be updated. Flag no prior task.
945
arl1:
946
        ldx             #-1
947
        bra             arl4
948 26 robfinch
 
949
;------------------------------------------------------------------------------
950
; RemoveTaskFromReadyList
951
; This subroutine removes a task from the ready list.
952
; This can be called from within an ISR.
953
;
954
; r1 = task number
955
;------------------------------------------------------------------------------
956
message "RemoveTaskFromReadyList"
957
RemoveTaskFromReadyList:
958 31 robfinch
        php                                             ; save off interrupt mask state
959 26 robfinch
        pha
960 28 robfinch
        phx
961 26 robfinch
        phy
962
        push    r4
963
        push    r5
964
 
965
        sei
966
        ld              r4,TCB_NxtRdy,r1        ; Get previous and next fields.
967
        ld              r5,TCB_PrvRdy,r1        ; if there is no previous task, then this is
968
        bmi             rfr1                    ; the head of the list. Update.
969
        st              r4,TCB_NxtRdy,r5
970
        cmp             r4,#0                   ; is there a next task to update ?
971 31 robfinch
        bmi             rfr4
972 26 robfinch
        st              r5,TCB_PrvRdy,r4
973 31 robfinch
        bra             rfr4
974 26 robfinch
 
975
        ; Update the head of the list
976
rfr1:
977
        ldy             TCB_Priority,r1
978
        st              r4,HeadRdy0,y
979
        cmp             r4,#0                   ; did we empty the list ?
980 28 robfinch
        bmi             rfr3
981 26 robfinch
        ld              r5,#-1                  ; flag no previous task for head of list
982
        st              r5,TCB_PrvRdy,r4
983 31 robfinch
rfr4:
984
        stz             TCB_NxtRdy,r1   ; Task is removed from ready list so the
985
        stz             TCB_PrvRdy,r1   ; contents of these fields shouldn't matter.
986
                                                        ; They are set to zero (the BIOS task) in case
987
                                                        ; there is a list problem.
988
 
989 28 robfinch
        ldx             TCB_Status,r1   ; set the task status to no longer ready.
990
        and             r2,r2,#~TS_READY
991
        stx             TCB_Status,r1
992
rfr2:
993 26 robfinch
        pop             r5
994
        pop             r4
995
        ply
996 28 robfinch
        plx
997 26 robfinch
        pla
998 31 robfinch
        plp
999 26 robfinch
rfr9:
1000
        rts
1001 28 robfinch
rfr3:
1002
        st              r4,TailRdy0,y   ;
1003
        bra             rfr4
1004
 
1005 26 robfinch
;------------------------------------------------------------------------------
1006 28 robfinch
; AddToTimeoutList
1007
; AddToTimeoutList adds a task to the timeout list. The task is placed in the
1008
; list depending on it's timeout value.
1009
;
1010
; Parameters:
1011
;       r1 = task
1012
;       r2 = timeout value
1013 26 robfinch
;------------------------------------------------------------------------------
1014
message "AddToTimeoutList"
1015
AddToTimeoutList:
1016 28 robfinch
        cmp             #0                                              ; quickly validate the task number
1017 31 robfinch
        bmi             RunningTCBErr                   ; must be between 0 and 255
1018
        cmp             #MAX_TASKNO
1019
        bpl             RunningTCBErr
1020 28 robfinch
 
1021 26 robfinch
        phx
1022
        push    r4
1023
        push    r5
1024
        php
1025
        sei
1026
 
1027
        ld              r5,#-1
1028
        ld              r4,TimeoutList  ; are there any tasks on the timeout list ?
1029
        bmi             attl1
1030
attl_check_next:
1031
        sub             r2,r2,TCB_Timeout,r4    ; is this timeout > next
1032
        bmi             attl_insert_before
1033
        ld              r5,r4
1034
        ld              r4,TCB_NxtRdy,r4
1035
        bpl             attl_check_next
1036
 
1037
        ; Here we scanned until the end of the timeout list and didn't find a
1038
        ; timeout of a greater value. So we add the task to the end of the list.
1039
attl_add_at_end:
1040
        st              r4,TCB_NxtRdy,r1        ; r4 was = -1
1041
        st              r1,TCB_NxtRdy,r5
1042
        st              r5,TCB_PrvRdy,r1
1043
        st              r2,TCB_Timeout,r1
1044
        bra             attl_exit
1045
 
1046
attl_insert_before:
1047
        cmp             r5,#-1
1048
        beq             attl2
1049
        st              r4,TCB_NxtRdy,r1        ; next on list goes after this task
1050
        st              r5,TCB_PrvRdy,r1        ; set previous link
1051
        st              r1,TCB_NxtRdy,r5
1052
        st              r1,TCB_PrvRdy,r4
1053
        bra             attl3
1054
 
1055
        ; Here there is no previous entry in the timeout list
1056
        ; Add at start
1057
attl2:
1058
        sta             TCB_PrvRdy,r4
1059
        st              r5,TCB_PrvRdy,r1        ; r5 = -1
1060
        st              r4,TCB_NxtRdy,r1
1061
        sta             TimeoutList             ; update the head pointer
1062
attl3:
1063
        add             r2,r2,TCB_Timeout,r4    ; get back timeout
1064
        stx             TCB_Timeout,r1
1065
        ld              r5,TCB_Timeout,r4       ; adjust the timeout of the next task
1066
        sub             r5,r5,r2
1067
        st              r5,TCB_Timeout,r4
1068
        bra             attl_exit
1069
 
1070
        ; Here there were no tasks on the timeout list, so we add at the
1071
        ; head of the list.
1072
attl1:
1073
        sta             TimeoutList             ; set the head of the timeout list
1074
        stx             TCB_Timeout,r1
1075
        ldx             #-1                             ; flag no more entries in timeout list
1076
        stx             TCB_NxtRdy,r1           ; no next entries
1077
        stx             TCB_PrvRdy,r1           ; and no prev entries
1078
attl_exit:
1079 28 robfinch
        ldx             TCB_Status,r1           ; set the task's status as timing out
1080
        or              r2,r2,#TS_TIMEOUT
1081
        stx             TCB_Status,r1
1082 26 robfinch
        plp
1083
        pop             r5
1084
        pop             r4
1085
        plx
1086 28 robfinch
attl4:
1087 26 robfinch
        rts
1088
 
1089
;------------------------------------------------------------------------------
1090 28 robfinch
; This subroutine is called from within the timer ISR when the task's
1091
; timeout expires.
1092 26 robfinch
;
1093
; r1 = task number
1094
;------------------------------------------------------------------------------
1095
message "RemoveFromTimeoutList"
1096
RemoveFromTimeoutList:
1097 28 robfinch
        cmp             #0                                              ; quickly validate the task number
1098 31 robfinch
        bmi             RunningTCBErr                   ; must be between 0 and 255
1099
        cmp             #MAX_TASKNO
1100
        bpl             RunningTCBErr
1101 28 robfinch
 
1102 26 robfinch
        pha
1103
        phx
1104
        push    r4
1105
        push    r5
1106
        php
1107
        sei
1108
 
1109
        ld              r4,TCB_PrvRdy,r1                ; adjust the links of the next and previous
1110
        bmi             rftl2
1111
        ld              r5,TCB_NxtRdy,r1                ; tasks on the list to point around the task
1112
        st              r5,TCB_NxtRdy,r4
1113
        bmi             rftl1
1114
        st              r4,TCB_PrvRdy,r5
1115
        ldx             TCB_Timeout,r1                  ; update the timeout of the next on list
1116
        add             r2,r2,TCB_Timeout,r5    ; with any remaining timeout in the task
1117
        stx             TCB_Timeout,r5                  ; removed from the list
1118
 
1119
        ; Here there is no next item on the list
1120
rftl1:
1121
        bra             rftl3
1122
 
1123
        ; Here there is no previous item on the list, so update the head of
1124
        ; the list.
1125
rftl2:
1126
        ld              r5,TCB_NxtRdy,r1
1127
        st              r5,TimeoutList          ; store next field into list head
1128
        bmi             rftl3
1129 28 robfinch
        ld              r4,TCB_Timeout,r1               ; add any remaining timeout to the timeout
1130
        add             r4,r4,TCB_Timeout,r5    ; of the next task on the list.
1131
        st              r4,TCB_Timeout,r5
1132
        ld              r4,#-1                                  ; there is no previous item to the head
1133 26 robfinch
        sta             TCB_PrvRdy,r5
1134
 
1135
        ; Here there is no previous or next items in the list, so the list
1136
        ; will be empty once this task is removed from it.
1137
rftl3:
1138 28 robfinch
        ldx             TCB_Status,r1           ; set the task status to not timing out
1139
        and             r2,r2,#~TS_TIMEOUT
1140
        stx             TCB_Status,r1
1141 26 robfinch
        plp
1142
        pop             r5
1143
        pop             r4
1144
        plx
1145
        pla
1146 28 robfinch
rft4:
1147 26 robfinch
        rts
1148 28 robfinch
 
1149 26 robfinch
;------------------------------------------------------------------------------
1150 28 robfinch
; Parameters:
1151 31 robfinch
; r1 = time duration in centi-seconds (1/100 second).
1152 28 robfinch
;------------------------------------------------------------------------------
1153
Sleep:
1154
        tax
1155
        sei
1156
        lda             RunningTCB
1157
        jsr             RemoveTaskFromReadyList
1158
        jsr             AddToTimeoutList
1159
        ldx             #SleepRet                       ; The scheduler will be returning to this
1160
        jmp             PushRegsAndRunTask      ; task eventually, once the timeout expires,
1161
                                                                ; so fake an interrupt call
1162
SleepRet:
1163
        cli
1164
        rts
1165
 
1166
;------------------------------------------------------------------------------
1167 26 robfinch
; Allocate a mailbox
1168
; r1 = pointer to place to store handle
1169
;------------------------------------------------------------------------------
1170
message "AllocMbx"
1171
AllocMbx:
1172
        cmp             #0
1173
        beq             ambx1
1174
        phx
1175
        phy
1176
        push    r4
1177
        ld              r4,r1
1178
        php
1179
        sei
1180
        lda             FreeMbx                 ; Get mailbox off of free mailbox list
1181
        sta             (r4)                    ; store off the mailbox number
1182
        bmi             ambx2
1183
        ldx             MBX_LINK,r1             ; and update the head of the list
1184
        stx             FreeMbx
1185
        dec             nMailbox                ; decrement number of available mailboxes
1186
        tax
1187
        ldy             RunningTCB                      ; set the mailbox owner
1188 31 robfinch
        bmi             RunningTCBErr
1189 26 robfinch
        lda             TCB_hJCB,y
1190
        sta             MBX_OWNER,x
1191
        lda             #-1                             ; initialize the head and tail of the queues
1192
        sta             MBX_TQ_HEAD,x
1193
        sta             MBX_TQ_TAIL,x
1194
        sta             MBX_MQ_HEAD,x
1195
        sta             MBX_MQ_TAIL,x
1196
        stz             MBX_TQ_COUNT,x  ; initialize counts to zero
1197
        stz             MBX_MQ_COUNT,x
1198
        stz             MBX_MQ_MISSED,x
1199
        lda             #8                              ; set the max queue size
1200
        sta             MBX_MQ_SIZE,x   ; and
1201
        lda             #MQS_NEWEST             ; queueing strategy
1202
        sta             MBX_MQ_STRATEGY,x
1203 31 robfinch
ambx3:
1204 26 robfinch
        plp
1205
        pop             r4
1206
        ply
1207
        plx
1208
        lda             #E_Ok
1209
        rts
1210
ambx1:
1211
        lda             #E_Arg
1212
        rts
1213
ambx2:
1214
        plp
1215
        pop             r4
1216
        ply
1217
        plx
1218
        lda             #E_NoMoreMbx
1219
        rts
1220
 
1221
;------------------------------------------------------------------------------
1222
; r1 = message
1223
; r2 = mailbox
1224
;------------------------------------------------------------------------------
1225
message "QueueMsgAtMbx"
1226
QueueMsgAtMbx:
1227
        pha
1228
        phx
1229
        phy
1230
        php
1231
        sei
1232
        ldy             MBX_MQ_TAIL,x
1233
        bmi             qmam1
1234
        sta             MBX_LINK,y
1235
        bra             qmam2
1236
qmam1:
1237
        sta             MBX_MQ_HEAD,x
1238
qmam2:
1239
        sta             MBX_MQ_TAIL,x
1240
        inc             MBX_MQ_COUNT,x          ; increase the queued message count
1241
        ldx             #-1
1242
        stx             MSG_LINK,r1
1243
        plp
1244
        ply
1245
        plx
1246
        pla
1247
        rts
1248
 
1249
;------------------------------------------------------------------------------
1250
; Returns
1251
; r1 = message number
1252
;------------------------------------------------------------------------------
1253
message "DequeueMsgFromMbx"
1254
DequeueMsgFromMbx:
1255
        phx
1256
        phy
1257
        php
1258
        sei
1259
        tax                                             ; x = mailbox index
1260
        lda             MBX_MQ_COUNT,x          ; are there any messages available ?
1261
        beq             dmfm1
1262
        dea
1263
        sta             MBX_MQ_COUNT,x          ; update the message count
1264
        lda             MBX_MQ_HEAD,x           ; Get the head of the list, this should not be -1
1265
        bmi             dmfm1                   ; since the message count > 0
1266
        ldy             MSG_LINK,r1             ; get the link to the next message
1267
        sty             MBX_MQ_HEAD,x           ; update the head of the list
1268
        bpl             dmfm2                   ; if there was no more messages then update the
1269
        sty             MBX_MQ_TAIL,x           ; tail of the list as well.
1270
dmfm2:
1271
        sta             MSG_LINK,r1             ; point the link to the messahe itself to indicate it's dequeued
1272
dmfm1:
1273
        plp
1274
        ply
1275
        plx
1276
        rts
1277
 
1278
;------------------------------------------------------------------------------
1279
;------------------------------------------------------------------------------
1280
DequeueThreadFromMbx:
1281
        cpx             #0
1282
        beq             dtfm1
1283
        php
1284
        sei
1285
        push    r4
1286
        ld              r4,MBX_TQ_HEAD,r1
1287
        bpl             dtfm2
1288
                pop             r4
1289
                stz             (x)
1290
                plp
1291
                lda             #E_NoThread
1292
                rts
1293
dtfm2:
1294
        push    r5
1295
        dec             MBX_TQ_COUNT,r1
1296
        st              r4,(x)
1297
        ld              r4,TCB_mbq_next,r4
1298
        st              r4,MBX_TQ_HEAD,r1
1299
        bmi             dtfm3
1300
                ld              r5,#-1
1301
                st              r5,TCB_mbq_prev,r4
1302
                bra             dtfm4
1303
dtfm3:
1304
                ld              r5,#-1
1305
                st              r5,MBX_TQ_TAIL,r1
1306
dtfm4:
1307
        stz             MBX_SEMA+1
1308
        ld              r5,(x)
1309
        lda             TCB_Status,r5
1310
        bit             #TS_TIMEOUT
1311
        beq             dtfm5
1312
                ld              r1,r5
1313
                jsr             RemoveFromTimeoutList
1314
dtfm5:
1315
        ld              r4,#-1
1316
        st              r4,TCB_mbq_next,r5
1317
        st              r4,TCB_mbq_prev,r5
1318
        stz             TCB_hWaitMbx,r5
1319
        lda             TCB_Status,r5
1320
        and             #~TS_WAITMSG
1321
        sta             TCB_Status,r5
1322
        pop             r5
1323
        pop             r4
1324
        plp
1325
        lda             #E_Ok
1326
        rts
1327
dtfm1:
1328
        lda             #E_Arg
1329
        rts
1330
 
1331
;------------------------------------------------------------------------------
1332
; r1 = handle to mailbox
1333
; r2 = message D1
1334
; r3 = message D2
1335
;------------------------------------------------------------------------------
1336
message "SendMsg"
1337
SendMsg:
1338
        cmp             #0                                              ; check the mailbox number to make sure
1339
        bmi             smsg1                                   ; that it's sensible
1340
        cmp             #2047
1341
        bpl             smsg1
1342
        push    r4
1343
        push    r5
1344
        push    r6
1345
        php
1346
        sei
1347
        ld              r4,MBX_OWNER,r1
1348
        bmi             smsg2                                   ; error: no owner
1349
        pha
1350
        phx
1351
        jsr             DequeueThreadFromMbx    ; r1=mbx, r2=thread (returned)
1352
        ld              r6,r2                                   ; r6 = thread
1353
        plx
1354
        pla
1355
        cmp             r6,#0
1356
        bpl             smsg3
1357
                ; Here there was no thread waiting at the mailbox, so a message needs to
1358
                ; be allocated
1359
                ld              r4,FreeMsg
1360
                bmi             smsg4           ; no more messages available
1361
                ld              r5,MSG_LINK,r4
1362
                st              r5,FreeMsg
1363
                dec             nMsgBlk         ; decrement the number of available messages
1364
                stx             MSG_D1,r4
1365
                sty             MSG_D2,r4
1366
                pha
1367
                phx
1368
                tax                                             ; x = mailbox
1369
                ld              r1,r4                   ; acc = message
1370
                jsr             QueueMsgAtMbx
1371
                plx
1372
                pla
1373
                cmp             r6,#0                   ; check if there is a thread waiting for a message
1374
                bmi             smsg5
1375
smsg3:
1376
        ld              r5,TCB_MSGPTR_D1,r6
1377
        beq             smsg6
1378
        stx             (r5)
1379
smsg6:
1380
        ld              r5,TCB_MSGPTR_D2,r6
1381
        beq             smsg7
1382
        sty             (r5)
1383
smsg7:
1384
        ld              r5,TCB_Status,r6
1385
        and             r5,r5,#TS_TIMEOUT
1386
        beq             smsg8
1387
        ld              r1,r6
1388
        jsr             RemoveFromTimeoutList
1389
smsg8:
1390
        ld              r1,r6
1391
        jsr             AddTaskToReadyList
1392
smsg5:
1393
        plp
1394
        pop             r6
1395
        pop             r5
1396
        pop             r4
1397
        lda             #E_Ok
1398
        rts
1399
smsg1:
1400
        lda             #E_BadMbx
1401
        rts
1402
smsg2:
1403
        plp
1404
        pop             r6
1405
        pop             r5
1406
        pop             r4
1407
        lda             #E_NotAlloc
1408
        rts
1409
smsg4:
1410
        plp
1411
        pop             r6
1412
        pop             r5
1413
        pop             r4
1414
        lda             #E_NoMsg
1415
        rts
1416
 
1417
;------------------------------------------------------------------------------
1418
; WaitMsg
1419
; Wait at a mailbox for a message to arrive. This subroutine will block the
1420
; task until a message is available or the task times out on the timeout
1421
; list.
1422
;
1423
; Parameters
1424
;       r1=mailbox
1425
;       r2=pointer to D1
1426
;       r3=pointer to D2
1427
;       r4=timeout
1428
; Returns:
1429
;       r1=E_Ok                 if everything is ok
1430
;       r1=E_BadMbx             for a bad mailbox number
1431
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1432
;------------------------------------------------------------------------------
1433
WaitMsg:
1434
        cmp             #0                                              ; check the mailbox number to make sure
1435
        bmi             wmsg1                                   ; that it's sensible
1436
        cmp             #2047
1437
        bpl             wmsg1
1438
        phx
1439
        phy
1440
        push    r4
1441
        push    r5
1442
        push    r6
1443
        push    r7
1444
        ld              r6,r1
1445
        php
1446
        sei
1447
        ld              r5,MBX_OWNER,r1
1448
        bmi             wmsg2                                   ; error: no owner
1449
        jsr             DequeueMsgFromMbx
1450
        cmp             #0
1451
        bpl             wmsg3
1452
 
1453
        ; Here there was no message available, remove the task from
1454
        ; the ready list, and optionally add it to the timeout list.
1455
        ; Queue the task at the mailbox.
1456
        lda             RunningTCB                              ; remove the task from the ready list
1457 31 robfinch
        bmi             wmsg8
1458 26 robfinch
        jsr             RemoveTaskFromReadyList
1459
        ld              r7,TCB_Status,r1                        ; set task status to waiting
1460
        or              r7,r7,#TS_WAITMSG
1461
        st              r7,TCB_Status,r1
1462
        st              r6,TCB_hWaitMbx,r1                      ; set which mailbox is waited for
1463
        ld              r7,#-1
1464
        st              r7,TCB_mbq_next,r1                      ; adding at tail, so there is no next
1465
        stx             TCB_MSGPTR_D1,r1                        ; save off the message pointers
1466
        sty             TCB_MSGPTR_D2,r1
1467
        ld              r7,MBX_TQ_HEAD,r1                       ; is there a task que setup at the mailbox ?
1468
        bmi             wmsg6
1469
        ld              r7,MBX_TQ_TAIL,r6
1470
        st              r7,TCB_mbq_prev,r1
1471
        sta             TCB_mbq_next,r7
1472
        sta             MBX_TQ_TAIL,r6
1473
        inc             MBX_TQ_COUNT,r6                         ; increment number of tasks queued
1474
wmsg7:
1475
        cmp             r4,#0                                           ; check for a timeout
1476
        beq             wmsg10
1477
        ld              r2,r4
1478
        jsr             AddToTimeoutList
1479
wmsg10:
1480
        ld              r2,#wmsg8                                       ; save the return address
1481 28 robfinch
PushRegsAndRunTask:
1482 26 robfinch
        phx
1483
        php                                                                     ; save status register
1484
        pha                                                                     ; and save the register set
1485
        phx
1486
        phy
1487
        push    r4
1488
        push    r5
1489
        push    r6
1490
        push    r7
1491
        push    r8
1492
        push    r9
1493
        push    r10
1494
        push    r11
1495
        push    r12
1496
        push    r13
1497
        push    r14
1498
        push    r15
1499
        jmp             SelectTaskToRun
1500
 
1501
        ; Here there were no prior tasks queued at the mailbox
1502
wmsg6:
1503
        ld              r7,#-1
1504
        st              r7,TCB_mbq_prev,r1              ; no previous tasks
1505
        st              r7,TCB_mbq_next,r1
1506
        sta             MBX_TQ_HEAD,r6                  ; set both head and tail indexes
1507
        sta             MBX_TQ_TAIL,r6
1508
        ld              r7,#1
1509
        st              r7,MBX_TQ_COUNT,r6              ; one task queued
1510
        bra             wmsg7                                   ; check for a timeout value
1511
 
1512
        ; Store message D1 to pointer
1513
wmsg3:
1514
        cpx             #0
1515
        beq             wmsg4
1516
        ld              r7,MSG_D1,r1
1517
        st              r7,(x)
1518
        ; Store message D2 to pointer
1519
wmsg4:
1520
        cpy             #0
1521
        beq             wmsg5
1522
        ld              r7,MSG_D2,r1
1523
        st              r7,(y)
1524
        ; Add the newly dequeued message to the free messsage list
1525
wmsg5:
1526
        ld              r7,FreeMsg
1527
        st              r7,MSG_LINK,r1
1528
        sta             FreeMsg
1529
        inc             nMsgBlk
1530
wmsg8:
1531
        plp
1532
        pop             r7
1533
        pop             r6
1534
        pop             r5
1535
        pop             r4
1536
        ply
1537
        plx
1538
        lda             #E_Ok
1539
        rts
1540
wmsg1:
1541
        lda             #E_BadMbx
1542
        rts
1543
wmsg2:
1544
        plp
1545
        pop             r7
1546
        pop             r6
1547
        pop             r5
1548
        pop             r4
1549
        ply
1550
        plx
1551
        lda             #E_NotAlloc
1552
        rts
1553
 
1554
;------------------------------------------------------------------------------
1555
; CheckMsg
1556
; Check for a message at a mailbox. Does not block.
1557
;
1558
; Parameters
1559
;       r1=mailbox
1560
;       r2=pointer to D1
1561
;       r3=pointer to D2
1562
;       r4=remove from queue if present
1563
; Returns:
1564
;       r1=E_Ok                 if everything is ok
1565
;       r1=E_NoMsg              if no message is available
1566
;       r1=E_BadMbx             for a bad mailbox number
1567
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1568
;------------------------------------------------------------------------------
1569
CheckMsg:
1570
        cmp             #0                                              ; check the mailbox number to make sure
1571
        bmi             cmsg1                                   ; that it's sensible
1572
        cmp             #2047
1573
        bpl             cmsg1
1574
        phx
1575
        phy
1576
        push    r4
1577
        push    r5
1578
        php
1579
        sei
1580
        ld              r5,MBX_OWNER,r1
1581
        bmi             cmsg2                                   ; error: no owner
1582
        cmp             r4,#0                                   ; are we to dequeue the message ?
1583
        beq             cmsg3
1584
        jsr             DequeueMsgFromMbx
1585
        bra             cmsg4
1586
cmsg3:
1587 28 robfinch
        lda             MBX_MQ_HEAD,r1                  ; peek the message at the head of the messages queue
1588 26 robfinch
cmsg4:
1589
        cmp             #0
1590
        bmi             cmsg5
1591
        cpx             #0
1592
        beq             cmsg6
1593
        ld              r5,MSG_D1,r1
1594
        st              r5,(x)
1595
cmsg6:
1596
        cpy             #0
1597
        beq             cmsg7
1598
        ld              r5,MSG_D2,r1
1599
        st              r5,(y)
1600
cmsg7:
1601
        cmp             r4,#0
1602
        beq             cmsg8
1603
        ld              r5,FreeMsg
1604
        st              r5,MSG_LINK,r1
1605
        sta             FreeMsg
1606
        inc             nMsgBlk
1607
cmsg8:
1608
        plp
1609
        pop             r5
1610
        pop             r4
1611
        ply
1612
        plx
1613
        lda             #E_Ok
1614
        rts
1615
cmsg1:
1616
        lda             #E_BadMbx
1617
        rts
1618
cmsg2:
1619
        plp
1620
        pop             r5
1621
        pop             r4
1622
        ply
1623
        plx
1624
        lda             #E_NotAlloc
1625
        rts
1626
cmsg5:
1627
        plp
1628
        pop             r5
1629
        pop             r4
1630
        ply
1631
        plx
1632
        lda             #E_NoMsg
1633
        rts
1634
 
1635
;------------------------------------------------------------------------------
1636
;------------------------------------------------------------------------------
1637 28 robfinch
SetIOFocusBit:
1638 31 robfinch
        and             r2,r2,#$FF
1639 28 robfinch
        and             r1,r2,#$1F              ; get bit index 0 to 31
1640
        ldy             #1
1641
        asl             r3,r3,r1                ; shift bit to proper place
1642
        lsr             r2,r2,#5                ; get word index /32 bits per word
1643
        lda             IOFocusTbl,x
1644
        or              r1,r1,r3
1645
        sta             IOFocusTbl,x
1646 26 robfinch
        rts
1647
 
1648
;------------------------------------------------------------------------------
1649
; The I/O focus list is an array indicating which tasks are requesting the
1650
; I/O focus. The I/O focus is user controlled by pressing ALT-TAB on the
1651
; keyboard.
1652
;------------------------------------------------------------------------------
1653
message "RequestIOFocus"
1654
RequestIOFocus:
1655
        pha
1656
        phx
1657
        phy
1658
        php
1659
        sei
1660 31 robfinch
        ldx             RunningTCB
1661 28 robfinch
        ldy             IOFocusNdx              ; Is the focus list empty ?
1662
        bmi             riof2
1663
riof4:
1664
        lda             TCB_iof_next,x  ; is the task already in the IO focus list ?
1665
        bpl             riof3
1666
        lda             IOFocusNdx              ; Expand the list
1667
        ldy             TCB_iof_prev,r1
1668
        stx             TCB_iof_prev,r1
1669
        sta             TCB_iof_next,x
1670
        sty             TCB_iof_prev,x
1671
        stx             TCB_iof_next,y
1672
riof3:
1673
        jsr             SetIOFocusBit
1674 26 robfinch
        plp
1675
        ply
1676
        plx
1677
        pla
1678
        rts
1679 28 robfinch
 
1680
        ; Here, the IO focus list was empty. So expand it.
1681
        ; Update pointers to loop back to self.
1682
riof2:
1683
        stx             IOFocusNdx
1684
        stx             TCB_iof_next,x
1685
        stx             TCB_iof_prev,x
1686
        bra             riof3
1687
 
1688
;------------------------------------------------------------------------------
1689
; Releasing the I/O focus causes the focus to switch if the running task
1690
; had the I/O focus.
1691
;------------------------------------------------------------------------------
1692 26 robfinch
message "ReleaseIOFocus"
1693
ReleaseIOFocus:
1694
        pha
1695
        phx
1696
        phy
1697
        php
1698
        sei
1699 28 robfinch
        ldx             RunningTCB
1700
        phx
1701
        ldy             #1
1702 26 robfinch
        and             r1,r2,#$1F              ; get bit index 0 to 31
1703
        asl             r3,r3,r1                ; shift bit to proper place
1704
        eor             r3,r3,#-1               ; invert bit mask
1705
        lsr             r2,r2,#5                ; get word index /32 bits per word
1706 28 robfinch
        lda             IOFocusTbl,x
1707 26 robfinch
        and             r1,r1,r3
1708 28 robfinch
        sta             IOFocusTbl,x
1709
        plx
1710
        cpx             IOFocusNdx              ; Does the running task have the I/O focus ?
1711
        bne             rliof1
1712
        jsr             SwitchIOFocus   ; If so, then switch the focus.
1713
rliof1:
1714
        lda             TCB_iof_next,x  ; get next and previous fields.
1715
        bmi             rliof2                  ; Is the task on the list ?
1716
        ldy             TCB_iof_prev,x
1717
        sta             TCB_iof_next,y  ; prev->next = current->next
1718
        sty             TCB_iof_prev,r1 ; next->prev = current->prev
1719
        cmp             r1,r3                   ; Check if the IO focus list is collapsing.
1720
        bne             rliof2                  ; If the list just points back to the task
1721
        cmp             r1,r2                   ; being removed, then it's the last task
1722
        bne             rliof2                  ; removed from the list, so the list is being
1723
        lda             #-1                             ; emptied.
1724
        sta             IOFocusNdx
1725
rliof2:
1726
        lda             #-1                             ; Update the next and prev fields to indicate
1727
        sta             TCB_iof_next,x  ; the task is no longer on the list.
1728
        sta             TCB_iof_prev,x
1729 31 robfinch
rliof3:
1730 26 robfinch
        plp
1731
        ply
1732
        plx
1733
        pla
1734
        rts
1735
 
1736
;------------------------------------------------------------------------------
1737 31 robfinch
; Get the location of the screen and screen attribute memory. The location
1738
; depends on whether or not the task has the output focus.
1739 26 robfinch
;------------------------------------------------------------------------------
1740
GetScreenLocation:
1741
        lda             RunningTCB
1742 28 robfinch
        cmp             IOFocusNdx
1743 26 robfinch
        beq             gsl1
1744 31 robfinch
        and             r1,r1,#$FF
1745 26 robfinch
        asl             r1,r1,#13                       ; 8192 words per screen
1746
        add             r1,r1,#BIOS_SCREENS
1747
        rts
1748
gsl1:
1749
        lda             #TEXTSCR
1750
        rts
1751
 
1752
GetColorCodeLocation:
1753
        lda             RunningTCB
1754 28 robfinch
        cmp             IOFocusNdx
1755 26 robfinch
        beq             gccl1
1756 31 robfinch
        and             r1,r1,#$FF
1757 26 robfinch
        asl             r1,r1,#13                       ; 8192 words per screen
1758
        add             r1,r1,#BIOS_SCREENS+4096
1759
        rts
1760
gccl1:
1761
        lda             #TEXTSCR+$10000
1762
        rts
1763
 
1764
;------------------------------------------------------------------------------
1765
;------------------------------------------------------------------------------
1766
message "CopyVirtualScreenToScreen"
1767
CopyVirtualScreenToScreen
1768
        pha
1769
        phx
1770
        phy
1771 28 robfinch
        push    r4
1772 26 robfinch
        lda             #4095                           ; number of words to copy-1
1773 28 robfinch
        ldx             IOFocusNdx                      ; compute virtual screen location
1774
        bmi             cvss3
1775 26 robfinch
        asl             r2,r2,#13                       ; 8192 words per screen
1776
        add             r2,r2,#BIOS_SCREENS     ; add in screens array base address
1777
        ldy             #TEXTSCR
1778 31 robfinch
        mvn
1779
;cvss1:
1780
;       ld              r4,(x)
1781
;       st              r4,(y)
1782
;       inx
1783
;       iny
1784
;       dea
1785
;       bne             cvss1
1786 26 robfinch
        ; now copy the color codes
1787
        lda             #4095
1788 28 robfinch
        ldx             IOFocusNdx
1789 26 robfinch
        asl             r2,r2,#13
1790
        add             r2,r2,#BIOS_SCREENS+4096        ; virtual char color array
1791
        ldy             #TEXTSCR+$10000
1792 31 robfinch
        mvn
1793
;cvss2:
1794
;       ld              r4,(x)
1795
;       st              r4,(y)
1796
;       inx
1797
;       iny
1798
;       dea
1799
;       bne             cvss2
1800 28 robfinch
cvss3:
1801
        ; reset the cursor position in the text controller
1802
        ldy             IOFocusNdx
1803
        ldx             TCB_CursorRow,y
1804
        lda             TEXTREG+TEXT_COLS
1805
        mul             r2,r2,r1
1806
        add             r2,r2,TCB_CursorCol,y
1807
        stx             TEXTREG+TEXT_CURPOS
1808
        pop             r4
1809 26 robfinch
        ply
1810
        plx
1811
        pla
1812
        rts
1813
message "CopyScreenToVirtualScreen"
1814
CopyScreenToVirtualScreen
1815
        pha
1816
        phx
1817
        phy
1818 28 robfinch
        push    r4
1819 26 robfinch
        lda             #4095
1820
        ldx             #TEXTSCR
1821 28 robfinch
        ldy             IOFocusNdx
1822
        bmi             csvs3
1823 26 robfinch
        asl             r3,r3,#13
1824
        add             r3,r3,#BIOS_SCREENS
1825 31 robfinch
        mvn
1826
;csvs1:
1827
;       ld              r4,(x)
1828
;       st              r4,(y)
1829
;       inx
1830
;       iny
1831
;       dea
1832
;       bne             csvs1
1833 26 robfinch
        lda             #4095
1834
        ldx             #TEXTSCR+$10000
1835 28 robfinch
        ldy             IOFocusNdx
1836 26 robfinch
        asl             r3,r3,#13
1837
        add             r3,r3,#BIOS_SCREENS+4096
1838 31 robfinch
        mvn
1839
;csvs2:
1840
;       ld              r4,(x)
1841
;       st              r4,(y)
1842
;       inx
1843
;       iny
1844
;       dea
1845
;       bne             csvs2
1846 28 robfinch
csvs3:
1847
        pop             r4
1848 26 robfinch
        ply
1849
        plx
1850
        pla
1851
        rts
1852
 
1853
;------------------------------------------------------------------------------
1854 11 robfinch
; Clear the screen and the screen color memory
1855
; We clear the screen to give a visual indication that the system
1856
; is working at all.
1857
;------------------------------------------------------------------------------
1858
;
1859 26 robfinch
message "ClearScreen"
1860 11 robfinch
ClearScreen:
1861
        pha                                                     ; holds a space character
1862
        phx                                                     ; loop counter
1863
        phy                                                     ; memory addressing
1864
        push    r4                                      ; holds the screen color
1865 26 robfinch
        push    r5
1866 11 robfinch
        lda             TEXTREG+TEXT_COLS       ; calc number to clear
1867
        ldx             TEXTREG+TEXT_ROWS
1868
        mul             r2,r1,r2                        ; r2 = # chars to clear
1869 26 robfinch
        jsr             GetScreenLocation
1870
        tay
1871
        jsr             GetColorCodeLocation
1872
        ld              r5,r1
1873 11 robfinch
        lda             #' '                            ; space char
1874
        ld              r4,ScreenColor
1875
        jsr             AsciiToScreen
1876
csj4:
1877
        sta             (y)
1878
        iny
1879 26 robfinch
        st              r4,(r5)
1880
        inc             r5
1881 11 robfinch
        dex
1882
        bne             csj4
1883 26 robfinch
        pop             r5
1884 11 robfinch
        pop             r4
1885
        ply
1886
        plx
1887
        pla
1888
        rts
1889
 
1890
;------------------------------------------------------------------------------
1891
; Scroll text on the screen upwards
1892
;------------------------------------------------------------------------------
1893
;
1894 26 robfinch
message "ScrollUp"
1895 11 robfinch
ScrollUp:
1896
        pha
1897
        phx
1898
        phy
1899
        push    r4
1900
        push    r5
1901 26 robfinch
        push    r6
1902 11 robfinch
        lda             TEXTREG+TEXT_COLS       ; acc = # text columns
1903
        ldx             TEXTREG+TEXT_ROWS
1904
        mul             r2,r1,r2                        ; calc number of chars to scroll
1905
        sub             r2,r2,r1                        ; one less row
1906 26 robfinch
        pha
1907
        jsr             GetScreenLocation
1908
        tay
1909
        jsr             GetColorCodeLocation
1910
        ld              r6,r1
1911
        pla
1912 11 robfinch
scrup1:
1913
        add             r5,r3,r1
1914
        ld              r4,(r5)                         ; move character
1915
        st              r4,(y)
1916 26 robfinch
        add             r5,r6,r1
1917
        ld              r4,(r5)                         ; and move color code
1918
        st              r4,(r6)
1919 11 robfinch
        iny
1920 26 robfinch
        inc             r6
1921 11 robfinch
        dex
1922
        bne             scrup1
1923
        lda             TEXTREG+TEXT_ROWS
1924
        dea
1925
        jsr             BlankLine
1926 26 robfinch
        pop             r6
1927 11 robfinch
        pop             r5
1928
        pop             r4
1929
        ply
1930
        plx
1931
        pla
1932
        rts
1933
 
1934
;------------------------------------------------------------------------------
1935
; Blank out a line on the display
1936
; line number to blank is in acc
1937
;------------------------------------------------------------------------------
1938
;
1939
BlankLine:
1940
        pha
1941
        phx
1942
        phy
1943 26 robfinch
        push    r4
1944 11 robfinch
        ldx             TEXTREG+TEXT_COLS       ; x = # chars to blank out from video controller
1945
        mul             r3,r2,r1                        ; y = screen index (row# * #cols)
1946 26 robfinch
        pha
1947
        jsr             GetScreenLocation
1948
        ld              r4,r1
1949
        pla
1950
        add             r3,r3,r4                ; y = screen address
1951 11 robfinch
        lda             #' '
1952 26 robfinch
        jsr             AsciiToScreen
1953 11 robfinch
blnkln1:
1954
        sta             (y)
1955
        iny
1956
        dex
1957
        bne             blnkln1
1958 26 robfinch
        pop             r4
1959 11 robfinch
        ply
1960
        plx
1961
        pla
1962
        rts
1963
 
1964
;------------------------------------------------------------------------------
1965
; Convert ASCII character to screen display character.
1966
;------------------------------------------------------------------------------
1967
;
1968
AsciiToScreen:
1969
        and             #$FF
1970
        cmp             #'A'
1971
        bcc             atoscr1         ; blt
1972
        cmp             #'Z'
1973
        bcc             atoscr1
1974
        beq             atoscr1
1975 15 robfinch
        cmp             #'z'+1
1976 11 robfinch
        bcs             atoscr1
1977
        cmp             #'a'
1978
        bcc             atoscr1
1979
        sub             #$60
1980
atoscr1:
1981
        or              #$100
1982
        rts
1983
 
1984
;------------------------------------------------------------------------------
1985
; Convert screen character to ascii character
1986
;------------------------------------------------------------------------------
1987
;
1988
ScreenToAscii:
1989
        and             #$FF
1990 15 robfinch
        cmp             #26+1
1991 11 robfinch
        bcs             stasc1
1992
        add             #$60
1993
stasc1:
1994
        rts
1995
 
1996
;------------------------------------------------------------------------------
1997 26 robfinch
; HomeCursor
1998
; Set the cursor location to the top left of the screen.
1999
;------------------------------------------------------------------------------
2000
HomeCursor:
2001
        phx
2002
        ldx             RunningTCB
2003 31 robfinch
        and             r2,r2,#$FF
2004 26 robfinch
        stz             TCB_CursorRow,x
2005
        stz             TCB_CursorCol,x
2006 31 robfinch
        cpx             IOFocusNdx
2007
        bne             hc1
2008
        stz             TEXTREG+TEXT_CURPOS
2009
hc1:
2010 26 robfinch
        plx
2011
        rts
2012
 
2013
;------------------------------------------------------------------------------
2014 31 robfinch
; Update the cursor position in the text controller based on the
2015
;  CursorRow,CursorCol.
2016
;------------------------------------------------------------------------------
2017
;
2018
UpdateCursorPos:
2019
        pha
2020
        phx
2021
        push    r4
2022
        ld              r4,RunningTCB
2023
        and             r4,r4,#$FF
2024
        cmp             r4,IOFocusNdx                   ; update cursor position in text controller
2025
        bne             ucp1                                    ; only for the task with the output focus
2026
        lda             TCB_CursorRow,r4
2027
        and             #$3F                                    ; limit of 63 rows
2028
        ldx             TEXTREG+TEXT_COLS
2029
        mul             r2,r2,r1
2030
        lda             TCB_CursorCol,r4
2031
        and             #$7F                                    ; limit of 127 cols
2032
        add             r2,r2,r1
2033
        stx             TEXTREG+TEXT_CURPOS
2034
ucp1:
2035
        pop             r4
2036
        plx
2037
        pla
2038
        rts
2039
 
2040
;------------------------------------------------------------------------------
2041 11 robfinch
; Calculate screen memory location from CursorRow,CursorCol.
2042
; Also refreshes the cursor location.
2043
; Returns:
2044
; r1 = screen location
2045
;------------------------------------------------------------------------------
2046
;
2047
CalcScreenLoc:
2048
        phx
2049 26 robfinch
        push    r4
2050
        ld              r4,RunningTCB
2051 31 robfinch
        and             r4,r4,#$FF
2052 26 robfinch
        lda             TCB_CursorRow,r4
2053 31 robfinch
        and             #$3F                                    ; limit to 63 rows
2054 11 robfinch
        ldx             TEXTREG+TEXT_COLS
2055
        mul             r2,r2,r1
2056 31 robfinch
        ld              r1,TCB_CursorCol,r4
2057
        and             #$7F                                    ; limit to 127 cols
2058
        add             r2,r2,r1
2059 28 robfinch
        cmp             r4,IOFocusNdx                   ; update cursor position in text controller
2060 26 robfinch
        bne             csl1                                    ; only for the task with the output focus
2061 11 robfinch
        stx             TEXTREG+TEXT_CURPOS
2062 26 robfinch
csl1:
2063
        jsr             GetScreenLocation
2064
        add             r1,r2,r1
2065 31 robfinch
        pop             r4
2066
        plx
2067
        rts
2068 26 robfinch
csl2:
2069 31 robfinch
        lda             #TEXTSCR
2070 26 robfinch
        pop             r4
2071 11 robfinch
        plx
2072
        rts
2073
 
2074
;------------------------------------------------------------------------------
2075 26 robfinch
; Display a character on the screen.
2076
; If the task doesn't have the I/O focus then the character is written to
2077
; the virtual screen.
2078 11 robfinch
; r1 = char to display
2079
;------------------------------------------------------------------------------
2080
;
2081 26 robfinch
message "DisplayChar"
2082 11 robfinch
DisplayChar:
2083 26 robfinch
        push    r4
2084
        ld              r4,RunningTCB
2085 31 robfinch
        and             r4,r4,#$FF
2086 26 robfinch
        and             #$FF                            ; mask off any higher order bits (called from eight bit mode).
2087 11 robfinch
        cmp             #'\r'                           ; carriage return ?
2088
        bne             dccr
2089 26 robfinch
        stz             TCB_CursorCol,r4        ; just set cursor column to zero on a CR
2090 31 robfinch
        jsr             UpdateCursorPos
2091
dcx14:
2092 26 robfinch
        pop             r4
2093 11 robfinch
        rts
2094
dccr:
2095
        cmp             #$91                            ; cursor right ?
2096
        bne             dcx6
2097
        pha
2098 26 robfinch
        lda             TCB_CursorCol,r4
2099 11 robfinch
        cmp             #83
2100
        bcs             dcx7
2101
        ina
2102 26 robfinch
        sta             TCB_CursorCol,r4
2103 11 robfinch
dcx7:
2104 31 robfinch
        jsr             UpdateCursorPos
2105 11 robfinch
        pla
2106 26 robfinch
        pop             r4
2107 11 robfinch
        rts
2108
dcx6:
2109
        cmp             #$90                            ; cursor up ?
2110
        bne             dcx8
2111
        pha
2112 26 robfinch
        lda             TCB_CursorRow,r4
2113 11 robfinch
        beq             dcx7
2114
        dea
2115 26 robfinch
        sta             TCB_CursorRow,r4
2116 11 robfinch
        bra             dcx7
2117
dcx8:
2118
        cmp             #$93                            ; cursor left ?
2119
        bne             dcx9
2120
        pha
2121 26 robfinch
        lda             TCB_CursorCol,r4
2122 11 robfinch
        beq             dcx7
2123
        dea
2124 26 robfinch
        sta             TCB_CursorCol,r4
2125 11 robfinch
        bra             dcx7
2126
dcx9:
2127
        cmp             #$92                            ; cursor down ?
2128
        bne             dcx10
2129
        pha
2130 26 robfinch
        lda             TCB_CursorRow,r4
2131 11 robfinch
        cmp             #46
2132
        beq             dcx7
2133
        ina
2134 26 robfinch
        sta             TCB_CursorRow,r4
2135 11 robfinch
        bra             dcx7
2136
dcx10:
2137
        cmp             #$94                            ; cursor home ?
2138
        bne             dcx11
2139
        pha
2140 26 robfinch
        lda             TCB_CursorCol,r4
2141 11 robfinch
        beq             dcx12
2142 26 robfinch
        stz             TCB_CursorCol,r4
2143 11 robfinch
        bra             dcx7
2144
dcx12:
2145 26 robfinch
        stz             TCB_CursorRow,r4
2146 11 robfinch
        bra             dcx7
2147
dcx11:
2148
        pha
2149
        phx
2150
        phy
2151
        cmp             #$99                            ; delete ?
2152
        bne             dcx13
2153
        jsr             CalcScreenLoc
2154
        tay                                                     ; y = screen location
2155 26 robfinch
        lda             TCB_CursorCol,r4        ; acc = cursor column
2156 11 robfinch
        bra             dcx5
2157
dcx13
2158
        cmp             #CTRLH                          ; backspace ?
2159
        bne             dcx3
2160 26 robfinch
        lda             TCB_CursorCol,r4
2161 11 robfinch
        beq             dcx4
2162
        dea
2163 26 robfinch
        sta             TCB_CursorCol,r4
2164 11 robfinch
        jsr             CalcScreenLoc           ; acc = screen location
2165
        tay                                                     ; y = screen location
2166 26 robfinch
        lda             TCB_CursorCol,r4
2167 11 robfinch
dcx5:
2168
        ldx             $4,y
2169
        stx             (y)
2170
        iny
2171
        ina
2172
        cmp             TEXTREG+TEXT_COLS
2173
        bcc             dcx5
2174
        lda             #' '
2175
        jsr             AsciiToScreen
2176
        dey
2177
        sta             (y)
2178
        bra             dcx4
2179
dcx3:
2180
        cmp             #'\n'                   ; linefeed ?
2181
        beq             dclf
2182
        tax                                             ; save acc in x
2183
        jsr     CalcScreenLoc   ; acc = screen location
2184
        tay                                             ; y = screen location
2185
        txa                                             ; restore r1
2186
        jsr             AsciiToScreen   ; convert ascii char to screen char
2187
        sta             (y)
2188 26 robfinch
        jsr             GetScreenLocation
2189
        sub             r3,r3,r1                ; make y an index into the screen
2190
        jsr             GetColorCodeLocation
2191
        add             r3,r3,r1
2192 11 robfinch
        lda             CharColor
2193 26 robfinch
        sta             (y)
2194 11 robfinch
        jsr             IncCursorPos
2195
        bra             dcx4
2196
dclf:
2197
        jsr             IncCursorRow
2198
dcx4:
2199
        ply
2200
        plx
2201
        pla
2202 26 robfinch
        pop             r4
2203 11 robfinch
        rts
2204
 
2205
;------------------------------------------------------------------------------
2206
; Increment the cursor position, scroll the screen if needed.
2207
;------------------------------------------------------------------------------
2208
;
2209
IncCursorPos:
2210
        pha
2211
        phx
2212 26 robfinch
        push    r4
2213
        ld              r4,RunningTCB
2214 31 robfinch
        and             r4,r4,#$FF
2215 26 robfinch
        lda             TCB_CursorCol,r4
2216 11 robfinch
        ina
2217 26 robfinch
        sta             TCB_CursorCol,r4
2218 11 robfinch
        ldx             TEXTREG+TEXT_COLS
2219
        cmp             r1,r2
2220
        bcc             icc1
2221 26 robfinch
        stz             TCB_CursorCol,r4                ; column = 0
2222 11 robfinch
        bra             icr1
2223
IncCursorRow:
2224
        pha
2225
        phx
2226 26 robfinch
        push    r4
2227
        ld              r4,RunningTCB
2228 31 robfinch
        and             r4,r4,#$FF
2229 11 robfinch
icr1:
2230 26 robfinch
        lda             TCB_CursorRow,r4
2231 11 robfinch
        ina
2232 26 robfinch
        sta             TCB_CursorRow,r4
2233 11 robfinch
        ldx             TEXTREG+TEXT_ROWS
2234
        cmp             r1,r2
2235
        bcc             icc1
2236
        beq             icc1
2237
        dex                                                     ; backup the cursor row, we are scrolling up
2238 26 robfinch
        stx             TCB_CursorRow,r4
2239 11 robfinch
        jsr             ScrollUp
2240
icc1:
2241 31 robfinch
        jsr             UpdateCursorPos
2242
icc2:
2243 26 robfinch
        pop             r4
2244 11 robfinch
        plx
2245
        pla
2246
        rts
2247
 
2248
;------------------------------------------------------------------------------
2249
; Display a string on the screen.
2250
; The characters are packed 4 per word
2251
;------------------------------------------------------------------------------
2252
;
2253
DisplayStringB:
2254
        pha
2255
        phx
2256
        tax                                             ; r2 = pointer to string
2257
dspj1B:
2258 15 robfinch
        lb              r1,0,x                  ; move string char into acc
2259 11 robfinch
        inx                                             ; increment pointer
2260
        cmp             #0                              ; is it end of string ?
2261
        beq             dsretB
2262
        jsr             DisplayChar             ; display character
2263 15 robfinch
        bra             dspj1B
2264 11 robfinch
dsretB:
2265
        plx
2266
        pla
2267
        rts
2268
 
2269 31 robfinch
DisplayStringQ:
2270
        pha
2271
        phx
2272
        tax                                             ; r2 = pointer to string
2273
        lda             #TEXTSCR
2274
        sta             QIndex
2275
dspj1Q:
2276
        lb              r1,0,x                  ; move string char into acc
2277
        inx                                             ; increment pointer
2278
        cmp             #0                              ; is it end of string ?
2279
        beq             dsretQ
2280
        jsr             DisplayCharQ    ; display character
2281
        bra             dspj1Q
2282
dsretQ:
2283
        plx
2284
        pla
2285
        rts
2286
 
2287
DisplayCharQ:
2288
        pha
2289
        phx
2290
        jsr             AsciiToScreen
2291
        ldx             #0
2292
        sta             (QIndex,x)
2293
        lda             QIndex
2294
        ina
2295
        sta             QIndex
2296
;       inc             QIndex
2297
        plx
2298
        pla
2299
        rts
2300
 
2301
 
2302 11 robfinch
;------------------------------------------------------------------------------
2303
; Display a string on the screen.
2304
; The characters are packed 1 per word
2305
;------------------------------------------------------------------------------
2306
;
2307
DisplayStringW:
2308
        pha
2309
        phx
2310
        tax                                             ; r2 = pointer to string
2311
dspj1W:
2312
        lda             (x)                             ; move string char into acc
2313
        inx                                             ; increment pointer
2314
        cmp             #0                              ; is it end of string ?
2315
        beq             dsretW
2316
        jsr             DisplayChar             ; display character
2317
        bra             dspj1W                  ; go back for next character
2318
dsretW:
2319
        plx
2320
        pla
2321
        rts
2322
 
2323
DisplayStringCRLFB:
2324
        jsr             DisplayStringB
2325
CRLF:
2326
        pha
2327
        lda             #'\r'
2328
        jsr             DisplayChar
2329
        lda             #'\n'
2330
        jsr             DisplayChar
2331
        pla
2332
        rts
2333
 
2334
;------------------------------------------------------------------------------
2335 15 robfinch
; Initialize keyboard
2336
;
2337
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
2338
; set #2 (the most common one). Also sets up the keyboard buffer and
2339
; initializes the keyboard semaphore.
2340
;------------------------------------------------------------------------------
2341
;
2342 26 robfinch
message "KeybdInit"
2343 15 robfinch
KeybdInit:
2344
        lda             #1                      ; setup semaphore
2345 26 robfinch
        sta             KEYBD_SEMA
2346 31 robfinch
        lda             #32
2347
        sta             LEDS
2348 26 robfinch
        ldx             #0
2349
kbdi1:
2350
        stz             KeybdHead,x             ; setup keyboard buffer
2351
        stz             KeybdTail,x
2352 15 robfinch
        lda             #1                      ; turn on keyboard echo
2353 26 robfinch
        sta             KeybdEcho,x
2354
        stz             KeybdBad,x
2355
        inx
2356 31 robfinch
        cpx             #MAX_TASKNO+1
2357 26 robfinch
        bne             kbdi1
2358 31 robfinch
 
2359
        lda             PIC_IE
2360
        or              r1,r1,#$8000            ; enable kbd_irq
2361
        sta             PIC_IE
2362
 
2363
        lda             #33
2364
        sta             LEDS
2365 15 robfinch
        lda             #$ff            ; issue keyboard reset
2366
        jsr             SendByteToKeybd
2367 31 robfinch
        lda             #38
2368
        sta             LEDS
2369 15 robfinch
        lda             #1000000                ; delay a bit
2370
kbdi5:
2371
        dea
2372 31 robfinch
        sta             LEDS
2373 15 robfinch
        bne             kbdi5
2374 31 robfinch
        lda             #34
2375
        sta             LEDS
2376 15 robfinch
        lda             #0xf0           ; send scan code select
2377
        jsr             SendByteToKeybd
2378 31 robfinch
        lda             #35
2379
        sta             LEDS
2380 15 robfinch
        ldx             #0xFA
2381
        jsr             WaitForKeybdAck
2382
        cmp             #$FA
2383
        bne             kbdi2
2384 31 robfinch
        lda             #36
2385
        sta             LEDS
2386 15 robfinch
        lda             #2                      ; select scan code set#2
2387
        jsr             SendByteToKeybd
2388 31 robfinch
        lda             #39
2389
        sta             LEDS
2390 15 robfinch
kbdi2:
2391
        rts
2392
 
2393
msgBadKeybd:
2394
        db              "Keyboard not responding.",0
2395
 
2396
SendByteToKeybd:
2397 26 robfinch
        phx
2398
        ldx             RunningTCB
2399 15 robfinch
        sta             KEYBD
2400 31 robfinch
        lda             #40
2401
        sta             LEDS
2402 15 robfinch
        tsr             TICK,r3
2403
kbdi4:                                          ; wait for transmit complete
2404
        tsr             TICK,r4
2405
        sub             r4,r4,r3
2406
        cmp             r4,#1000000
2407
        bcs             kbdbad
2408 31 robfinch
        lda             #41
2409
        sta             LEDS
2410 15 robfinch
        lda             KEYBD+3
2411
        bit             #64
2412
        beq             kbdi4
2413
        bra             sbtk1
2414
kbdbad:
2415 31 robfinch
        lda             #42
2416
        sta             LEDS
2417 26 robfinch
        lda             KeybdBad,x
2418 15 robfinch
        bne             sbtk1
2419
        lda             #1
2420 26 robfinch
        sta             KeybdBad,x
2421 31 robfinch
        lda             #43
2422
        sta             LEDS
2423 15 robfinch
        lda             #msgBadKeybd
2424
        jsr             DisplayStringCRLFB
2425
sbtk1:
2426 31 robfinch
        lda             #44
2427
        sta             LEDS
2428 26 robfinch
        plx
2429 15 robfinch
        rts
2430
 
2431
; Wait for keyboard to respond with an ACK (FA)
2432
;
2433
WaitForKeybdAck:
2434 31 robfinch
        lda             #64
2435
        sta             LEDS
2436 15 robfinch
        tsr             TICK,r3
2437
wkbdack1:
2438
        tsr             TICK,r4
2439
        sub             r4,r4,r3
2440
        cmp             r4,#1000000
2441
        bcs             wkbdbad
2442 31 robfinch
        lda             #65
2443
        sta             LEDS
2444 15 robfinch
        lda             KEYBD
2445
        bit             #$8000
2446
        beq             wkbdack1
2447
;       lda             KEYBD+8
2448
        and             #$ff
2449
wkbdbad:
2450
        rts
2451
 
2452
; Wait for keyboard to respond with an ACK (FA)
2453
; This routine picks up the ack status left by the
2454
; keyboard IRQ routine.
2455
; r2 = 0xFA (could also be 0xEE for echo command)
2456
;
2457
WaitForKeybdAck2:
2458 26 robfinch
        phx
2459
        ldx             RunningTCB
2460
WaitForKeybdAck2a:
2461
        lda             KeybdAck,x
2462 15 robfinch
        cmp             r1,r2
2463 26 robfinch
        bne             WaitForKeybdAck2a
2464
        stz             KeybdAck,x
2465
        plx
2466 15 robfinch
        rts
2467
 
2468
;------------------------------------------------------------------------------
2469
; Normal keyboard interrupt, the lowest priority interrupt in the system.
2470
; Grab the character from the keyboard device and store it in a buffer.
2471 26 robfinch
; The buffer of the task with the input focus is updated.
2472 15 robfinch
;------------------------------------------------------------------------------
2473
;
2474 26 robfinch
message "KeybdIRQ"
2475 15 robfinch
KeybdIRQ:
2476 26 robfinch
        cld
2477 15 robfinch
        pha
2478
        phx
2479
        phy
2480 26 robfinch
        push    r4
2481
 
2482
        ; support EhBASIC's IRQ functionality
2483
        ; code derived from minimon.asm
2484
        lda             #15                             ; Keyboard is IRQ #15
2485
        sta             IrqSource
2486
        lb              r1,IrqBase              ; get the IRQ flag byte
2487
        lsr             r2,r1
2488
        or              r1,r1,r2
2489
        and             #$E0
2490
        sb              r1,IrqBase              ; save the new IRQ flag byte
2491
 
2492 28 robfinch
        ld              r4,IOFocusNdx   ; get the task with the input focus
2493 26 robfinch
 
2494 15 robfinch
        ldx             KEYBD                           ; get keyboard character
2495
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
2496
        txy                                                     ; check for a keyboard ACK code
2497
        and             r3,r3,#$ff
2498
        cmp             r3,#$FA
2499
        bne             KeybdIrq1
2500 26 robfinch
        sty             KeybdAck,r4
2501 15 robfinch
        bra             KeybdIRQc
2502
KeybdIrq1:
2503
        bit             r2,#$800                                ; test bit #11
2504
        bne             KeybdIRQc                               ; ignore keyup messages for now
2505 26 robfinch
KeybdIrq2:
2506
        lda             KeybdHead,r4
2507 15 robfinch
        ina                                                             ; increment head pointer
2508
        and             #$f                                             ; limit
2509 26 robfinch
        ldy             KeybdTail,r4                    ; check for room in the keyboard buffer
2510 15 robfinch
        cmp             r1,r3
2511
        beq             KeybdIRQc                               ; if no room, the newest char will be lost
2512 26 robfinch
        sta             KeybdHead,r4
2513 15 robfinch
        dea
2514
        and             #$f
2515 26 robfinch
        stx             KeybdLocks,r4
2516
        asl             r4,r4,#4                                        ; * 16
2517
        add             r1,r1,r4
2518 15 robfinch
        stx             KeybdBuffer,r1                  ; store character in buffer
2519
KeybdIRQc:
2520 26 robfinch
        pop             r4
2521 15 robfinch
        ply
2522
        plx
2523
        pla
2524
        rti
2525
 
2526
KeybdRstIRQ:
2527 26 robfinch
        jmp             start
2528 15 robfinch
 
2529
;------------------------------------------------------------------------------
2530
; r1 0=echo off, non-zero = echo on
2531
;------------------------------------------------------------------------------
2532
SetKeyboardEcho:
2533 26 robfinch
        phx
2534
        ldx             RunningTCB
2535
        sta             KeybdEcho,x
2536
        plx
2537 15 robfinch
        rts
2538
 
2539 26 robfinch
;------------------------------------------------------------------------------
2540
; Get a bit from the I/O focus table.
2541
;------------------------------------------------------------------------------
2542
GetIOFocusBit:
2543
        phx
2544
        phy
2545
        tax
2546
        and             r1,r1,#$1F              ; get bit index into word
2547
        lsr             r2,r2,#5                ; get word index into table
2548 28 robfinch
        ldy             IOFocusTbl,x
2549 26 robfinch
        lsr             r3,r3,r1                ; extract bit
2550
        and             r1,r3,#1
2551
        ply
2552
        plx
2553
        rts
2554
 
2555
;------------------------------------------------------------------------------
2556
; SwitchIOFocus
2557 31 robfinch
;
2558 28 robfinch
; Switches the IO focus to the next task requesting the I/O focus. This
2559
; routine may be called when a task releases the I/O focus as well as when
2560
; the user presses ALT-TAB on the keyboard.
2561 26 robfinch
;------------------------------------------------------------------------------
2562
;
2563
SwitchIOFocus:
2564 28 robfinch
        pha
2565
        phy
2566 26 robfinch
 
2567 28 robfinch
        ; First check if it's even possible to switch the focus to another
2568
        ; task. The I/O focus list could be empty or there may be only a
2569
        ; single task in the list. In either case it's not possible to
2570
        ; switch.
2571
        ldy             IOFocusNdx              ; Get the task at the head of the list.
2572
        bmi             siof3                   ; Is the list empty ?
2573
        lda             TCB_iof_next,y  ; Get the next task on the list.
2574
        cmp             r1,r3                   ; Will the list head change ?
2575
        beq             siof3                   ; If not then no switch will occur
2576
 
2577
        ; Copy the current task's screen to it's virtual screen buffer.
2578
        jsr             CopyScreenToVirtualScreen
2579 26 robfinch
 
2580 28 robfinch
        sta             IOFocusNdx              ; Make task the new head of list.
2581 31 robfinch
 
2582 26 robfinch
        ; Copy the virtual screen of the task recieving the I/O focus to the
2583
        ; text screen.
2584
        jsr             CopyVirtualScreenToScreen
2585 28 robfinch
siof3:
2586
        ply
2587
        pla
2588 26 robfinch
        rts
2589
 
2590
;------------------------------------------------------------------------------
2591 15 robfinch
; Get character from keyboard buffer
2592
; return character in acc or -1 if no
2593 26 robfinch
; characters available.
2594
; Also check for ALT-TAB and switch the I/O focus.
2595
;------------------------------------------------------------------------------
2596
message "KeybdGetChar"
2597 15 robfinch
KeybdGetChar:
2598
        phx
2599 26 robfinch
        push    r4
2600
        php
2601
        sei
2602
        ld              r4,RunningTCB
2603 31 robfinch
        bmi             RunningTCBErr
2604
        cmp             #MAX_TASKNO
2605
        bpl             RunningTCBErr
2606 26 robfinch
        ldx             KeybdTail,r4    ; if keybdTail==keybdHead then there are no
2607
        lda             KeybdHead,r4    ; characters in the keyboard buffer
2608 15 robfinch
        cmp             r1,r2
2609
        beq             nochar
2610 26 robfinch
        asl             r4,r4,#4                        ; * 16
2611
        phx
2612
        add             r2,r2,r4
2613 15 robfinch
        lda             KeybdBuffer,x
2614 26 robfinch
        plx
2615
        bit             #$200                                   ; check for ALT-tab
2616
        beq             kgc4
2617
        and             #$FF
2618
        cmp             #TAB                                    ; if we find an ALT-tab
2619
        bne             kgc4
2620
        jsr             SwitchIOFocus
2621
        ; Now eat up the ALT-TAB character
2622 28 robfinch
        ; Flush the keyboard buffer
2623
        lsr             r4,r4,#4
2624
        stz             KeybdTail,r4
2625
        stz             KeybdHead,r4
2626 26 robfinch
        bra             nochar
2627
kgc4:
2628 15 robfinch
        and             r1,r1,#$ff              ; mask off control bits
2629
        inx                                             ; increment index
2630
        and             r2,r2,#$0f
2631 26 robfinch
        lsr             r4,r4,#4                        ; / 16
2632
        stx             KeybdTail,r4
2633
        ldx             KeybdEcho,r4
2634 15 robfinch
        beq             kgc3
2635
        cmp             #CR
2636 26 robfinch
        bne             kgc8
2637 15 robfinch
        jsr             CRLF                    ; convert CR keystroke into CRLF
2638
        bra             kgc3
2639 26 robfinch
kgc8:
2640 15 robfinch
        jsr             DisplayChar
2641
        bra             kgc3
2642
nochar:
2643
        lda             #-1
2644
kgc3:
2645 26 robfinch
        plp
2646
        pop             r4
2647 15 robfinch
        plx
2648
        rts
2649
 
2650
;------------------------------------------------------------------------------
2651
; Check if there is a keyboard character available in the keyboard buffer.
2652 26 robfinch
; Returns
2653
; r1 = 1, Z=0 if there is a key available, otherwise
2654
; r1 = 0, Z=1 if there is not a key available
2655 15 robfinch
;------------------------------------------------------------------------------
2656
;
2657 26 robfinch
message "KeybdCheckForKey"
2658 15 robfinch
KeybdCheckForKey:
2659
        phx
2660 26 robfinch
        push    r4
2661
        php
2662
        sei
2663
        ld              r4,RunningTCB
2664
        lda             KeybdTail,r4
2665
        ldx             KeybdHead,r4
2666 15 robfinch
        sub             r1,r1,r2
2667
        bne             kcfk1
2668 26 robfinch
        plp
2669
        pop             r4
2670 15 robfinch
        plx
2671 26 robfinch
        lda             #0
2672 15 robfinch
        rts
2673
kcfk1
2674 26 robfinch
        plp
2675
        pop             r4
2676
        plx
2677 15 robfinch
        lda             #1
2678
        rts
2679
;------------------------------------------------------------------------------
2680
; Check if there is a keyboard character available. If so return true (1)
2681
; otherwise return false (0) in r1.
2682
;------------------------------------------------------------------------------
2683
;
2684 26 robfinch
message "KeybdCheckForKeyDirect"
2685 15 robfinch
KeybdCheckForKeyDirect:
2686
        lda             KEYBD
2687
        and             #$8000
2688
        beq             kcfkd1
2689
        lda             #1
2690
kcfkd1
2691
        rts
2692
 
2693
;------------------------------------------------------------------------------
2694
; Get character directly from keyboard. This routine blocks until a key is
2695
; available.
2696
;------------------------------------------------------------------------------
2697
;
2698
KeybdGetCharDirect:
2699
        phx
2700
kgc1:
2701
        lda             KEYBD
2702
        bit             #$8000
2703
        beq             kgc1
2704
        ld              r0,KEYBD+1              ; clear keyboard strobe
2705
        bit             #$800                   ; is it a keydown event ?
2706
        bne             kgc1
2707 26 robfinch
        bit             #$200                           ; check for ALT-tab
2708
        bne             kgc2
2709
        and             r2,r1,#$7f
2710
        cmp             r2,#TAB                                 ; if we find an ALT-tab
2711
        bne             kgc2
2712
        jsr             SwitchIOFocus
2713
        bra             kgc1
2714
kgc2:
2715 15 robfinch
        and             #$ff                    ; remove strobe bit
2716
        ldx             KeybdEcho               ; is keyboard echo on ?
2717
        beq             gk1
2718
        cmp             #CR
2719
        bne             gk2                             ; convert CR keystroke into CRLF
2720
        jsr             CRLF
2721
        bra             gk1
2722
gk2:
2723
        jsr             DisplayChar
2724
gk1:
2725
        plx
2726
        rts
2727
 
2728
 
2729 26 robfinch
;==============================================================================
2730
; Serial port
2731
;==============================================================================
2732 15 robfinch
;------------------------------------------------------------------------------
2733 26 robfinch
; Initialize the serial port
2734
; r1 = low 28 bits = baud rate
2735
; r2 = other settings
2736
; The desired baud rate must fit in 28 bits or less.
2737
;------------------------------------------------------------------------------
2738
;
2739
SerialInit:
2740
;       asl             r1,r1,#4                        ; * 16
2741
;       shlui   r1,r1,#32                       ; * 2^32
2742
;       inhu    r2,CR_CLOCK                     ; get clock frequency from config record
2743
;       divu    r1,r1,r2                        ; / clock frequency
2744
 
2745
        lsr             r1,r1,#8                        ; drop the lowest 8 bits
2746
        sta             UART_CM1                        ; set LSB
2747
        lsr             r1,r1,#8
2748
        sta             UART_CM2                        ; set middle bits
2749
        lsr             r1,r1,#8
2750
        sta             UART_CM3                        ; set MSB
2751
        stz             Uart_rxhead                     ; reset buffer indexes
2752
        stz             Uart_rxtail
2753
        lda             #0x1f0
2754
        sta             Uart_foff                       ; set threshold for XOFF
2755
        lda             #0x010
2756
        sta             Uart_fon                        ; set threshold for XON
2757
        lda             #1
2758
        sta             UART_IE                         ; enable receive interrupt only
2759
        stz             Uart_rxrts                      ; no RTS/CTS signals available
2760
        stz             Uart_txrts                      ; no RTS/CTS signals available
2761
        stz             Uart_txdtr                      ; no DTR signals available
2762
        stz             Uart_rxdtr                      ; no DTR signals available
2763
        lda             #1
2764
        sta             Uart_txxon                      ; for now
2765
        lda             #1
2766
        sta             SERIAL_SEMA
2767
        rts
2768
 
2769
;---------------------------------------------------------------------------------
2770
; Get character directly from serial port. Blocks until a character is available.
2771
;---------------------------------------------------------------------------------
2772
;
2773
SerialGetCharDirect:
2774
sgc1:
2775
        lda             UART_LS         ; uart status
2776
        and             #rxfull         ; is there a char available ?
2777
        beq             sgc1
2778
        lda             UART
2779
        rts
2780
 
2781
;------------------------------------------------
2782
; Check for a character at the serial port
2783
; returns r1 = 1 if char available, 0 otherwise
2784
;------------------------------------------------
2785
;
2786
SerialCheckForCharDirect:
2787
        lda             UART_LS                 ; uart status
2788
        and             #rxfull                 ; is there a char available ?
2789
        rts
2790
 
2791
;-----------------------------------------
2792
; Put character to serial port
2793
; r1 = char to put
2794
;-----------------------------------------
2795
;
2796
SerialPutChar:
2797
        phx
2798
        phy
2799
        push    r4
2800
        push    r5
2801
 
2802
        ldx             UART_MC
2803
        or              r2,r2,#3                ; assert DTR / RTS
2804
        stx             UART_MC
2805
        ldx             Uart_txrts
2806
        beq             spcb1
2807
        ld              r4,Milliseconds
2808
        ldy             #1000                   ; delay count (1 s)
2809
spcb3:
2810
        ldx             UART_MS
2811
        and             r2,r2,#$10              ; is CTS asserted ?
2812
        bne             spcb1
2813
        ld              r5,Milliseconds
2814
        cmp             r4,r5
2815
        beq             spcb3
2816
        ld              r4,r5
2817
        dey
2818
        bne             spcb3
2819
        bra             spcabort
2820
spcb1:
2821
        ldx             Uart_txdtr
2822
        beq             spcb2
2823
        ld              r4,Milliseconds
2824
        ldy             #1000                   ; delay count
2825
spcb4:
2826
        ldx             UART_MS
2827
        and             r2,r2,#$20              ; is DSR asserted ?
2828
        bne             spcb2
2829
        ld              r5,Milliseconds
2830
        cmp             r4,r5
2831
        beq             spcb4
2832
        ld              r4,r5
2833
        dey
2834
        bne             spcb4
2835
        bra             spcabort
2836
spcb2:
2837
        ldx             Uart_txxon
2838
        beq             spcb5
2839
spcb6:
2840
        ldx             Uart_txxonoff
2841
        beq             spcb5
2842
        ld              r4,UART_MS
2843
        and             r4,r4,#0x80                     ; DCD ?
2844
        bne             spcb6
2845
spcb5:
2846
        ld              r4,Milliseconds
2847
        ldy             #1000                           ; wait up to 1s
2848
spcb8:
2849
        ldx             UART_LS
2850
        and             r2,r2,#0x20                     ; tx not full ?
2851
        bne             spcb7
2852
        ld              r5,Milliseconds
2853
        cmp             r4,r5
2854
        beq             spcb8
2855
        ld              r4,r5
2856
        dey
2857
        bne             spcb8
2858
        bra             spcabort
2859
spcb7:
2860
        sta             UART
2861
spcabort:
2862
        pop             r5
2863
        pop             r4
2864
        ply
2865
        plx
2866
        rts
2867
 
2868
;-------------------------------------------------
2869
; Compute number of characters in recieve buffer.
2870
; r4 = number of chars
2871
;-------------------------------------------------
2872
CharsInRxBuf:
2873
        ld              r4,Uart_rxhead
2874
        ldx             Uart_rxtail
2875
        sub             r4,r4,r2
2876
        bpl             cirxb1
2877
        ld              r4,#0x200
2878
        add             r4,r4,r2
2879
        ldx             Uart_rxhead
2880
        sub             r4,r4,r2
2881
cirxb1:
2882
        rts
2883
 
2884
;----------------------------------------------
2885
; Get character from rx fifo
2886
; If the fifo is empty enough then send an XON
2887
;----------------------------------------------
2888
;
2889
SerialGetChar:
2890
        phx
2891
        phy
2892
        push    r4
2893
 
2894
        ldy             Uart_rxhead
2895
        ldx             Uart_rxtail
2896
        cmp             r2,r3
2897
        beq             sgcfifo1                ; is there a char available ?
2898
        lda             Uart_rxfifo,x   ; get the char from the fifo into r1
2899
        inx                                             ; increment the fifo pointer
2900
        and             r2,r2,#$1ff
2901
        stx             Uart_rxtail
2902
        ldx             Uart_rxflow             ; using flow control ?
2903
        beq             sgcfifo2
2904
        ldy             Uart_fon                ; enough space in Rx buffer ?
2905
        jsr             CharsInRxBuf
2906
        cmp             r4,r3
2907
        bpl             sgcfifo2
2908
        stz             Uart_rxflow             ; flow off
2909
        ld              r4,Uart_rxrts
2910
        beq             sgcfifo3
2911
        ld              r4,UART_MC              ; set rts bit in MC
2912
        or              r4,r4,#2
2913
        st              r4,UART_MC
2914
sgcfifo3:
2915
        ld              r4,Uart_rxdtr
2916
        beq             sgcfifo4
2917
        ld              r4,UART_MC              ; set DTR
2918
        or              r4,r4,#1
2919
        st              r4,UART_MC
2920
sgcfifo4:
2921
        ld              r4,Uart_rxxon
2922
        beq             sgcfifo5
2923
        ld              r4,#XON
2924
        st              r4,UART
2925
sgcfifo5:
2926
sgcfifo2:                                       ; return with char in r1
2927
        pop             r4
2928
        ply
2929
        plx
2930
        rts
2931
sgcfifo1:
2932
        lda             #-1                             ; no char available
2933
        pop             r4
2934
        ply
2935
        plx
2936
        rts
2937
 
2938
 
2939
;-----------------------------------------
2940
; Serial port IRQ
2941
;-----------------------------------------
2942
;
2943
SerialIRQ:
2944
        pha
2945
        phx
2946
        phy
2947
        push    r4
2948
 
2949
        lda             UART_IS                 ; get interrupt status
2950
        bpl             sirq1                   ; no interrupt
2951
        and             #0x7f                   ; switch on interrupt type
2952
        cmp             #4
2953
        beq             srxirq
2954
        cmp             #$0C
2955
        beq             stxirq
2956
        cmp             #$10
2957
        beq             smsirq
2958
        ; unknown IRQ type
2959
sirq1:
2960
        pop             r4
2961
        ply
2962
        plx
2963
        pla
2964
        rti
2965
 
2966
 
2967
; Get the modem status and record it
2968
smsirq:
2969
        lda             UART_MS
2970
        sta             Uart_ms
2971
        bra             sirq1
2972
 
2973
stxirq:
2974
        bra             sirq1
2975
 
2976
; Get a character from the uart and store it in the rx fifo
2977
srxirq:
2978
srxirq1:
2979
        lda             UART                            ; get the char (clears interrupt)
2980
        ldx             Uart_txxon
2981
        beq             srxirq3
2982
        cmp             #XOFF
2983
        bne             srxirq2
2984
        lda             #1
2985
        sta             Uart_txxonoff
2986
        bra             srxirq5
2987
srxirq2:
2988
        cmp             #XON
2989
        bne             srxirq3
2990
        stz             Uart_txxonoff
2991
        bra             srxirq5
2992
srxirq3:
2993
        stz             Uart_txxonoff
2994
        ldx             Uart_rxhead
2995
        sta             Uart_rxfifo,x           ; store in buffer
2996
        inx
2997
        and             r2,r2,#$1ff
2998
        stx             Uart_rxhead
2999
srxirq5:
3000
        lda             UART_LS                         ; check for another ready character
3001
        and             #rxfull
3002
        bne             srxirq1
3003
        lda             Uart_rxflow                     ; are we using flow controls?
3004
        bne             srxirq8
3005
        jsr             CharsInRxBuf
3006
        lda             Uart_foff
3007
        cmp             r4,r1
3008
        bmi             srxirq8
3009
        lda             #1
3010
        sta             Uart_rxflow
3011
        lda             Uart_rxrts
3012
        beq             srxirq6
3013
        lda             UART_MC
3014
        and             #$FD                    ; turn off RTS
3015
        sta             UART_MC
3016
srxirq6:
3017
        lda             Uart_rxdtr
3018
        beq             srxirq7
3019
        lda             UART_MC
3020
        and             #$FE                    ; turn off DTR
3021
        sta             UART_MC
3022
srxirq7:
3023
        lda             Uart_rxxon
3024
        beq             srxirq8
3025
        lda             #XOFF
3026
        sta             UART
3027
srxirq8:
3028
        bra             sirq1
3029
 
3030
 
3031
;------------------------------------------------------------------------------
3032 11 robfinch
; Display nybble in r1
3033
;------------------------------------------------------------------------------
3034
;
3035
DisplayNybble:
3036
        pha
3037
        and             #$0F
3038
        add             #'0'
3039 15 robfinch
        cmp             #'9'+1
3040 11 robfinch
        bcc             dispnyb1
3041
        add             #7
3042
dispnyb1:
3043
        jsr             DisplayChar
3044
        pla
3045
        rts
3046
 
3047
;------------------------------------------------------------------------------
3048
; Display the byte in r1
3049
;------------------------------------------------------------------------------
3050
;
3051
DisplayByte:
3052
        pha
3053 18 robfinch
        lsr             r1,r1,#4
3054 11 robfinch
        jsr             DisplayNybble
3055
        pla
3056
        jmp             DisplayNybble   ; tail rts
3057 15 robfinch
message "785"
3058
;------------------------------------------------------------------------------
3059
; Display the half-word in r1
3060
;------------------------------------------------------------------------------
3061
;
3062
DisplayHalf:
3063
        pha
3064 18 robfinch
        lsr             r1,r1,#8
3065 15 robfinch
        jsr             DisplayByte
3066
        pla
3067
        jsr             DisplayByte
3068
        rts
3069 11 robfinch
 
3070 15 robfinch
message "797"
3071 11 robfinch
;------------------------------------------------------------------------------
3072 15 robfinch
; Display the half-word in r1
3073 11 robfinch
;------------------------------------------------------------------------------
3074 15 robfinch
;
3075
DisplayWord:
3076
        pha
3077 18 robfinch
        lsr             r1,r1,#16
3078 15 robfinch
        jsr             DisplayHalf
3079
        pla
3080
        jsr             DisplayHalf
3081
        rts
3082
message "810"
3083
;------------------------------------------------------------------------------
3084
; Display memory pointed to by r2.
3085
; destroys r1,r3
3086
;------------------------------------------------------------------------------
3087
;
3088
DisplayMemW:
3089
        pha
3090
        lda             #':'
3091
        jsr             DisplayChar
3092
        txa
3093
        jsr             DisplayWord
3094
        lda             #' '
3095
        jsr             DisplayChar
3096
        lda             (x)
3097
        jsr             DisplayWord
3098
        inx
3099
        lda             #' '
3100
        jsr             DisplayChar
3101
        lda             (x)
3102
        jsr             DisplayWord
3103
        inx
3104
        lda             #' '
3105
        jsr             DisplayChar
3106
        lda             (x)
3107
        jsr             DisplayWord
3108
        inx
3109
        lda             #' '
3110
        jsr             DisplayChar
3111
        lda             (x)
3112
        jsr             DisplayWord
3113
        inx
3114
        jsr             CRLF
3115
        pla
3116
        rts
3117 26 robfinch
 
3118
message "Monitor"
3119 15 robfinch
;==============================================================================
3120
; System Monitor Program
3121 26 robfinch
; The system monitor is task#0
3122 15 robfinch
;==============================================================================
3123
;
3124
Monitor:
3125 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer
3126 15 robfinch
        txs
3127 28 robfinch
        lda             #0                                      ; turn off keyboard echo
3128
        jsr             SetKeyboardEcho
3129
        jsr             RequestIOFocus
3130 15 robfinch
PromptLn:
3131
        jsr             CRLF
3132
        lda             #'$'
3133
        jsr             DisplayChar
3134
 
3135
; Get characters until a CR is keyed
3136
;
3137
Prompt3:
3138 28 robfinch
        jsr             RequestIOFocus
3139 15 robfinch
;       lw              r1,#2                   ; get keyboard character
3140
;       syscall #417
3141 26 robfinch
;       jsr             KeybdCheckForKeyDirect
3142
;       cmp             #0
3143
        jsr             KeybdGetChar
3144
        cmp             #-1
3145 15 robfinch
        beq             Prompt3
3146 26 robfinch
;       jsr             KeybdGetCharDirect
3147 15 robfinch
        cmp             #CR
3148
        beq             Prompt1
3149
        jsr             DisplayChar
3150
        bra             Prompt3
3151
 
3152
; Process the screen line that the CR was keyed on
3153
;
3154
Prompt1:
3155 31 robfinch
        lda             #80
3156
        sta             LEDS
3157 26 robfinch
        ldx             RunningTCB
3158 31 robfinch
        bmi             RunningTCBErr
3159
        cpx             #MAX_TASKNO
3160
        bpl             RunningTCBErr
3161
        lda             #81
3162
        sta             LEDS
3163 26 robfinch
        stz             TCB_CursorCol,x ; go back to the start of the line
3164 15 robfinch
        jsr             CalcScreenLoc   ; r1 = screen memory location
3165
        tay
3166 31 robfinch
        lda             #82
3167
        sta             LEDS
3168 15 robfinch
        lda             (y)
3169
        iny
3170
        jsr             ScreenToAscii
3171
        cmp             #'$'
3172
        bne             Prompt2                 ; skip over '$' prompt character
3173 31 robfinch
        lda             #83
3174
        sta             LEDS
3175 15 robfinch
        lda             (y)
3176
        iny
3177
        jsr             ScreenToAscii
3178
 
3179
; Dispatch based on command character
3180
;
3181
Prompt2:
3182
        cmp             #':'
3183
        beq             EditMem
3184
        cmp             #'D'
3185 18 robfinch
        bne             Prompt8
3186
        lda             (y)
3187
        iny
3188
        jsr             ScreenToAscii
3189
        cmp             #'R'
3190
        beq             DumpReg
3191 31 robfinch
        cmp             #'I'
3192
        beq             DoDir
3193 18 robfinch
        dey
3194
        bra             DumpMem
3195
Prompt8:
3196 15 robfinch
        cmp             #'F'
3197 28 robfinch
        bne             Prompt7
3198
        lda             (y)
3199
        iny
3200
        jsr             ScreenToAscii
3201
        cmp             #'L'
3202
        bne             Prompt8a
3203
        jsr             DumpIOFocusList
3204
        jmp             Monitor
3205
Prompt8a:
3206 31 robfinch
        cmp             #'M'
3207
        beq             DoFmt
3208 28 robfinch
        dey
3209
        bra             FillMem
3210 15 robfinch
Prompt7:
3211
        cmp             #'B'                    ; $B - start tiny basic
3212
        bne             Prompt4
3213 26 robfinch
        lda             #3
3214
        ldy             #CSTART
3215
        ldx             #0
3216
        jsr             StartTask
3217
;       jsr             CSTART
3218 15 robfinch
        bra             Monitor
3219
Prompt4:
3220
        cmp             #'b'
3221
        bne             Prompt5
3222 26 robfinch
        lda             #3                              ; priority level 3
3223
        ldy             #$C000                  ; start address $C000
3224
        ldx             #$20000000              ; flags: emmulation mode set
3225
        jsr             StartTask
3226
        bra             Monitor
3227 15 robfinch
        emm
3228
        cpu             W65C02
3229
        jml             $0C000
3230
        cpu             rtf65002
3231
Prompt5:
3232
        cmp             #'J'                    ; $J - execute code
3233
        beq             ExecuteCode
3234 26 robfinch
        cmp             #'L'                    ; $L - load dector
3235
        beq             LoadSector
3236
        cmp             #'W'
3237
        beq             WriteSector
3238 15 robfinch
Prompt9:
3239
        cmp             #'?'                    ; $? - display help
3240
        bne             Prompt10
3241
        lda             #HelpMsg
3242
        jsr             DisplayStringB
3243
        jmp             Monitor
3244
Prompt10:
3245
        cmp             #'C'                    ; $C - clear screen
3246
        beq             TestCLS
3247 26 robfinch
        cmp             #'r'
3248 15 robfinch
        bne             Prompt12
3249 26 robfinch
        lda             #4                              ; priority level 4
3250
        ldx             #0                              ; zero all flags at startup
3251
        ldy             #RandomLines    ; task address
3252
        jsr             (y)
3253
;       jsr             StartTask
3254
        jmp             Monitor
3255
;       jmp             RandomLinesCall
3256 15 robfinch
Prompt12:
3257
Prompt13:
3258
        cmp             #'P'
3259
        bne             Prompt14
3260 31 robfinch
        lda             #2
3261
        ldx             #0
3262
        ldy             #Piano
3263
        jsr             StartTask
3264
        jmp             Monitor
3265 15 robfinch
Prompt14:
3266
        cmp             #'T'
3267
        bne             Prompt15
3268 26 robfinch
        jsr             DumpTaskList
3269
        jmp             Monitor
3270 15 robfinch
Prompt15:
3271
        cmp             #'S'
3272
        bne             Prompt16
3273 28 robfinch
        lda             (y)
3274
        iny
3275
        jsr             ScreenToAscii
3276
        cmp             #'P'
3277
        bne             Prompt18
3278
        jsr             ignBlanks
3279
        jsr             GetHexNumber
3280
        sta             SPSave
3281
        jmp             Monitor
3282
Prompt18:
3283
        dey
3284 15 robfinch
        jsr             spi_init
3285
        cmp             #0
3286
        bne             Monitor
3287
        jsr             spi_read_part
3288
        cmp             #0
3289
        bne             Monitor
3290
        jsr             spi_read_boot
3291
        cmp             #0
3292
        bne             Monitor
3293
        jsr             loadBootFile
3294
        jmp             Monitor
3295
Prompt16:
3296 26 robfinch
        cmp             #'e'
3297
        bne             Prompt17
3298
        jsr             eth_main
3299
Prompt17:
3300
        cmp             #'R'
3301
        bne             Monitor
3302
        lda             (y)
3303
        iny
3304
        jsr             ScreenToAscii
3305
        cmp             #'S'
3306 28 robfinch
        beq             LoadSector
3307 26 robfinch
        dey
3308
        bra             SetRegValue
3309 15 robfinch
        jmp             Monitor
3310
message "Prompt16"
3311
RandomLinesCall:
3312 26 robfinch
;       jsr             RandomLines
3313 15 robfinch
        jmp             Monitor
3314
 
3315 31 robfinch
DoDir:
3316
        jsr             do_dir
3317
        jmp             Monitor
3318
DoFmt:
3319
        jsr             do_fmt
3320
        jmp             Monitor
3321
 
3322 15 robfinch
TestCLS:
3323
        lda             (y)
3324
        iny
3325
        jsr             ScreenToAscii
3326
        cmp             #'L'
3327
        bne             Monitor
3328
        lda             (y)
3329
        iny
3330
        jsr             ScreenToAscii
3331
        cmp             #'S'
3332
        bne             Monitor
3333
        jsr     ClearScreen
3334 26 robfinch
        ldx             RunningTCB
3335
        stz             TCB_CursorCol,x
3336
        stz             TCB_CursorRow,x
3337 15 robfinch
        jsr             CalcScreenLoc
3338
        jmp             Monitor
3339 26 robfinch
message "HelpMsg"
3340 15 robfinch
HelpMsg:
3341
        db      "? = Display help",CR,LF
3342
        db      "CLS = clear screen",CR,LF
3343
        db      "S = Boot from SD Card",CR,LF
3344
        db      ": = Edit memory bytes",CR,LF
3345 26 robfinch
        db      "L = Load sector",CR,LF
3346
        db      "W = Write sector",CR,LF
3347 18 robfinch
        db  "DR = Dump registers",CR,LF
3348 15 robfinch
        db      "D = Dump memory",CR,LF
3349
        db      "F = Fill memory",CR,LF
3350 28 robfinch
        db  "FL = Dump I/O Focus List",CR,LF
3351 15 robfinch
        db      "B = start tiny basic",CR,LF
3352
        db      "b = start EhBasic 6502",CR,LF
3353
        db      "J = Jump to code",CR,LF
3354 18 robfinch
        db      "R[n] = Set register value",CR,LF
3355 26 robfinch
        db      "r = random lines - test bitmap",CR,LF
3356
        db      "e = ethernet test",CR,LF
3357
        db      "T = Dump task list",CR,LF
3358 15 robfinch
        db      "P = Piano",CR,LF,0
3359
 
3360
;------------------------------------------------------------------------------
3361
; Ignore blanks in the input
3362
; r3 = text pointer
3363
; r1 destroyed
3364
;------------------------------------------------------------------------------
3365
;
3366
ignBlanks:
3367
ignBlanks1:
3368
        lda             (y)
3369
        iny
3370
        jsr             ScreenToAscii
3371
        cmp             #' '
3372
        beq             ignBlanks1
3373
        dey
3374
        rts
3375
 
3376
;------------------------------------------------------------------------------
3377
; Edit memory byte(s).
3378
;------------------------------------------------------------------------------
3379
;
3380
EditMem:
3381
        jsr             ignBlanks
3382
        jsr             GetHexNumber
3383
        or              r5,r1,r0
3384
        ld              r4,#3
3385
edtmem1:
3386
        jsr             ignBlanks
3387
        jsr             GetHexNumber
3388
        sta             (r5)
3389
        add             r5,r5,#1
3390
        dec             r4
3391
        bne             edtmem1
3392
        jmp             Monitor
3393
 
3394
;------------------------------------------------------------------------------
3395
; Execute code at the specified address.
3396
;------------------------------------------------------------------------------
3397
;
3398 26 robfinch
message "ExecuteCode"
3399 15 robfinch
ExecuteCode:
3400
        jsr             ignBlanks
3401
        jsr             GetHexNumber
3402 18 robfinch
        st              r1,JMPTMP
3403
        lda             #xcret                  ; push return address so we can do an indirect jump
3404
        pha
3405
        ld              r1,R1Save
3406
        ld              r2,R2Save
3407
        ld              r3,R3Save
3408
        ld              r4,R4Save
3409
        ld              r5,R5Save
3410
        ld              r6,R6Save
3411
        ld              r7,R7Save
3412
        ld              r8,R8Save
3413
        ld              r9,R9Save
3414
        ld              r10,R10Save
3415
        ld              r11,R11Save
3416
        ld              r12,R12Save
3417
        ld              r13,R13Save
3418
        ld              r14,R14Save
3419
        ld              r15,R15Save
3420
        jmp             (JMPTMP)
3421
xcret:
3422
        php
3423
        st              r1,R1Save
3424
        st              r2,R2Save
3425
        st              r3,R3Save
3426
        st              r4,R4Save
3427
        st              r5,R5Save
3428
        st              r6,R6Save
3429
        st              r7,R7Save
3430
        st              r8,R8Save
3431
        st              r9,R9Save
3432
        st              r10,R10Save
3433
        st              r11,R11Save
3434
        st              r12,R12Save
3435
        st              r13,R13Save
3436
        st              r14,R14Save
3437
        st              r15,R15Save
3438
        tsr             sp,r1
3439 28 robfinch
        st              r1,SPSave
3440 18 robfinch
        tsr             sp8,r1
3441 28 robfinch
        st              r1,SP8Save
3442 18 robfinch
        pla
3443
        sta             SRSave
3444 15 robfinch
        jmp     Monitor
3445
 
3446
LoadSector:
3447
        jsr             ignBlanks
3448 26 robfinch
        jsr             GetDecNumber
3449
        pha
3450
        jsr             ignBlanks
3451 15 robfinch
        jsr             GetHexNumber
3452 26 robfinch
        tax
3453
        phx
3454
;       ld              r2,#0x3800
3455
        jsr             spi_init
3456
        plx
3457
        pla
3458 15 robfinch
        jsr             spi_read_sector
3459
        jmp             Monitor
3460
 
3461 26 robfinch
WriteSector:
3462
        jsr             ignBlanks
3463
        jsr             GetDecNumber
3464
        pha
3465
        jsr             ignBlanks
3466
        jsr             GetHexNumber
3467
        tax
3468
        phx
3469
        jsr             spi_init
3470
        plx
3471
        pla
3472
        jsr             spi_write_sector
3473
        jmp             Monitor
3474
 
3475 15 robfinch
;------------------------------------------------------------------------------
3476 18 robfinch
; Dump the register set.
3477
;------------------------------------------------------------------------------
3478 26 robfinch
message "DumpReg"
3479 18 robfinch
DumpReg:
3480
        ldy             #0
3481
DumpReg1:
3482
        jsr             CRLF
3483
        lda             #':'
3484
        jsr             DisplayChar
3485
        lda             #'R'
3486
        jsr             DisplayChar
3487 26 robfinch
        ldx             #1
3488 18 robfinch
        tya
3489 26 robfinch
        ina
3490 18 robfinch
        jsr             PRTNUM
3491
        lda             #' '
3492
        jsr             DisplayChar
3493
        lda             R1Save,y
3494
        jsr             DisplayWord
3495
        iny
3496
        cpy             #15
3497
        bne             DumpReg1
3498
        jsr             CRLF
3499
        lda             #':'
3500
        jsr             DisplayChar
3501
        lda             #'S'
3502
        jsr             DisplayChar
3503
        lda             #'P'
3504
        jsr             DisplayChar
3505
        lda             #' '
3506
        jsr             DisplayChar
3507 26 robfinch
        lda             TCB_SPSave
3508 18 robfinch
        jsr             DisplayWord
3509
        jsr             CRLF
3510 26 robfinch
        jmp             Monitor
3511
;------------------------------------------------------------------------------
3512
;------------------------------------------------------------------------------
3513
SetRegValue:
3514
        jsr             GetDecNumber
3515
        cmp             #15
3516
        bpl             Monitor
3517
        pha
3518
        jsr             ignBlanks
3519
        jsr             GetHexNumber
3520
        ply
3521
        sta             R1Save,y
3522
        jmp             Monitor
3523 18 robfinch
 
3524
;------------------------------------------------------------------------------
3525 15 robfinch
; Do a memory dump of the requested location.
3526
;------------------------------------------------------------------------------
3527
;
3528
DumpMem:
3529
        jsr             ignBlanks
3530
        jsr             GetHexNumber    ; get start address of dump
3531
        tax
3532
        jsr             ignBlanks
3533
        jsr             GetHexNumber    ; get number of words to dump
3534
        lsr                                             ; 1/4 as many dump rows
3535
        lsr
3536
        bne             Dumpmem2
3537
        lda             #1                              ; dump at least one row
3538
Dumpmem2:
3539
        jsr             CRLF
3540
        bra             DumpmemW
3541
DumpmemW:
3542
        jsr             DisplayMemW
3543
        dea
3544
        bne             DumpmemW
3545
        jmp             Monitor
3546
 
3547
 
3548
        bra             Monitor
3549 26 robfinch
message "FillMem"
3550 15 robfinch
FillMem:
3551
        jsr             ignBlanks
3552
        jsr             GetHexNumber    ; get start address of dump
3553
        tax
3554
        jsr             ignBlanks
3555
        jsr             GetHexNumber    ; get number of bytes to fill
3556 26 robfinch
        ld              r5,r1
3557 15 robfinch
        jsr             ignBlanks
3558
        jsr             GetHexNumber    ; get the fill byte
3559
FillmemW:
3560
        sta             (x)
3561
        inx
3562
        dec             r5
3563
        bne             FillmemW
3564
        jmp             Monitor
3565
 
3566
;------------------------------------------------------------------------------
3567
; Get a hexidecimal number. Maximum of eight digits.
3568
; R3 = text pointer (updated)
3569
; R1 = hex number
3570
;------------------------------------------------------------------------------
3571
;
3572
GetHexNumber:
3573
        phx
3574
        push    r4
3575
        ldx             #0
3576
        ld              r4,#8
3577
gthxn2:
3578
        lda             (y)
3579
        iny
3580
        jsr             ScreenToAscii
3581
        jsr             AsciiToHexNybble
3582
        cmp             #-1
3583
        beq             gthxn1
3584 18 robfinch
        asl             r2,r2,#4
3585 15 robfinch
        and             #$0f
3586
        or              r2,r2,r1
3587
        dec             r4
3588
        bne             gthxn2
3589
gthxn1:
3590
        txa
3591
        pop             r4
3592
        plx
3593
        rts
3594
 
3595 26 robfinch
GetDecNumber:
3596
        phx
3597
        push    r4
3598
        push    r5
3599
        ldx             #0
3600
        ld              r4,#10
3601
        ld              r5,#10
3602
gtdcn2:
3603
        lda             (y)
3604
        iny
3605
        jsr             ScreenToAscii
3606
        jsr             AsciiToDecNybble
3607
        cmp             #-1
3608
        beq             gtdcn1
3609
        mul             r2,r2,r5
3610
        add             r2,r2,r1
3611
        dec             r4
3612
        bne             gtdcn2
3613
gtdcn1:
3614
        txa
3615
        pop             r5
3616
        pop             r4
3617
        plx
3618
        rts
3619
 
3620 15 robfinch
;------------------------------------------------------------------------------
3621
; Convert ASCII character in the range '0' to '9', 'a' to 'f' or 'A' to 'F'
3622
; to a hex nybble.
3623
;------------------------------------------------------------------------------
3624
;
3625
AsciiToHexNybble:
3626
        cmp             #'0'
3627
        bcc             gthx3
3628
        cmp             #'9'+1
3629
        bcs             gthx5
3630
        sub             #'0'
3631
        rts
3632
gthx5:
3633
        cmp             #'A'
3634
        bcc             gthx3
3635
        cmp             #'F'+1
3636
        bcs             gthx6
3637
        sub             #'A'
3638
        add             #10
3639
        rts
3640
gthx6:
3641
        cmp             #'a'
3642
        bcc             gthx3
3643
        cmp             #'z'+1
3644
        bcs             gthx3
3645
        sub             #'a'
3646
        add             #10
3647
        rts
3648
gthx3:
3649
        lda             #-1             ; not a hex number
3650
        rts
3651
 
3652 26 robfinch
AsciiToDecNybble:
3653
        cmp             #'0'
3654
        bcc             gtdc3
3655
        cmp             #'9'+1
3656
        bcs             gtdc3
3657
        sub             #'0'
3658
        rts
3659
gtdc3:
3660
        lda             #-1
3661
        rts
3662
 
3663
 
3664 15 robfinch
;------------------------------------------------------------------------------
3665
;------------------------------------------------------------------------------
3666 11 robfinch
ClearBmpScreen:
3667
        pha
3668
        phx
3669
        phy
3670
        ldx             #(1364*768)>>2          ; x = # words to clear
3671
        lda             #0x29292929                     ; acc = color for four pixels
3672
        ldy             #BITMAPSCR                      ; y = screen address
3673 15 robfinch
cbsj4
3674 11 robfinch
        sta             (y)                                     ; store pixel data
3675
        iny                                                     ; advance screen address
3676
        dex                                                     ; decrement pixel count and loop back
3677 15 robfinch
        bne             cbsj4
3678 11 robfinch
        ply
3679
        plx
3680
        pla
3681
        rts
3682
 
3683
;==============================================================================
3684
;==============================================================================
3685 28 robfinch
;--------------------------------------------------------------------------
3686
; Setup the AC97/LM4550 audio controller. Check keyboard for a CTRL-C
3687
; interrupt which may be necessary if the audio controller isn't
3688
; responding.
3689
;--------------------------------------------------------------------------
3690 11 robfinch
;
3691 28 robfinch
SetupAC97:
3692
        pha
3693
        phx
3694
        phy
3695
        push    r4
3696
        ld              r4,Milliseconds
3697
sac974:
3698
        stz             AC97+0x26               ; trigger a read of register 26 (status reg)
3699
sac971:                                         ; wait for status to register 0xF (all ready)
3700
        ld              r3,Milliseconds
3701
        sub             r3,r3,r4
3702
        cmp             r3,#1000
3703
        bpl             sac97Abort
3704
        jsr             KeybdGetChar    ; see if we needed to CTRL-C
3705
        cmp             #CTRLC
3706
        beq             sac973
3707
        lda             AC97+0x68               ; wait for dirty bit to clear
3708
        bne             sac971
3709
        lda             AC97+0x26               ; check status at reg h26, wait for
3710
        and             #0x0F                   ; analogue to be ready
3711
        cmp             #$0F
3712
        bne             sac974
3713
sac973:
3714
        stz             AC97+2                  ; master volume, 0db attenuation, mute off
3715
        stz             AC97+4                  ; headphone volume, 0db attenuation, mute off
3716
        stz             AC97+0x18               ; PCM gain (mixer) mute off, no attenuation
3717
        stz             AC97+0x0A               ; mute PC beep
3718
        lda             #0x8000                 ; bypass 3D sound
3719
        sta             AC97+0x20
3720
        ld              r4,Milliseconds
3721
sac972:
3722
        ld              r3,Milliseconds
3723
        sub             r3,r3,r4
3724
        cmp             r3,#1000
3725
        bpl             sac97Abort
3726
        jsr             KeybdGetChar
3727
        cmp             #CTRLC
3728
        beq             sac975
3729
        lda             AC97+0x68               ; wait for dirty bits to clear
3730
        bne             sac972                  ; wait a while for the settings to take effect
3731
sac975:
3732
        pop             r4
3733
        ply
3734
        plx
3735
        pla
3736
        rts
3737
sac97Abort:
3738
        lda             #msgAC97bad
3739
        jsr             DisplayStringCRLFB
3740
        pop             r4
3741
        ply
3742
        plx
3743
        pla
3744
        rts
3745
 
3746
msgAC97bad:
3747
        db      "The AC97 controller is not responding.",CR,LF,0
3748
 
3749
;--------------------------------------------------------------------------
3750
; Sound a 800 Hz beep
3751
;--------------------------------------------------------------------------
3752
;
3753
Beep:
3754
        pha
3755
        lda             #15                             ; master volume to max
3756
        sta             PSG+128
3757
        lda             #13422                  ; 800Hz
3758
        sta             PSGFREQ0
3759
        ; decay  (16.384 ms)2
3760
        ; attack (8.192 ms)1
3761
        ; release (1.024 s)A
3762
        ; sustain level C
3763
        lda             #0xCA12
3764
        sta             PSGADSR0
3765
        lda             #0x1104                 ; gate, output enable, triangle waveform
3766
        sta             PSGCTRL0
3767 31 robfinch
        lda             #100                    ; delay about 1s
3768
        jsr             Sleep
3769 28 robfinch
        lda             #0x0104                 ; gate off, output enable, triangle waveform
3770
        sta             PSGCTRL0
3771 31 robfinch
        lda             #100                    ; delay about 1s
3772
        jsr             Sleep
3773 28 robfinch
        lda             #0x0000                 ; gate off, output enable off, no waveform
3774
        sta             PSGCTRL0
3775
        pla
3776
        rts
3777
 
3778
;--------------------------------------------------------------------------
3779
;--------------------------------------------------------------------------
3780
;
3781
Piano:
3782 31 robfinch
        jsr             RequestIOFocus
3783 28 robfinch
        lda             #15                             ; master volume to max
3784
        sta             PSG+128
3785
playnt:
3786
        jsr             KeybdGetChar
3787
        cmp             #CTRLC
3788 31 robfinch
        beq             PianoX
3789 28 robfinch
        cmp             #'a'
3790
        beq             playnt1a
3791
        cmp             #'b'
3792
        beq             playnt1b
3793
        cmp             #'c'
3794
        beq             playnt1c
3795
        cmp             #'d'
3796
        beq             playnt1d
3797
        cmp             #'e'
3798
        beq             playnt1e
3799
        cmp             #'f'
3800
        beq             playnt1f
3801
        cmp             #'g'
3802
        beq             playnt1g
3803
        bra             playnt
3804 31 robfinch
PianoX:
3805
        jsr             ReleaseIOFocus
3806
        rts
3807 28 robfinch
 
3808
playnt1a:
3809
        lda             #7217
3810
        jsr             Tone
3811
        bra             playnt
3812
playnt1b:
3813
        lda             #8101
3814
        jsr             Tone
3815
        bra             playnt
3816
playnt1c:
3817
        lda             #4291
3818
        jsr             Tone
3819
        bra             playnt
3820
playnt1d:
3821
        lda             #4817
3822
        jsr             Tone
3823
        bra             playnt
3824
playnt1e:
3825
        lda             #5407
3826
        jsr             Tone
3827
        bra             playnt
3828
playnt1f:
3829
        lda             #5728
3830
        jsr             Tone
3831
        bra             playnt
3832
playnt1g:
3833
        lda             #6430
3834
        jsr             Tone
3835
        bra             playnt
3836
 
3837
Tone:
3838
        pha
3839
        sta             PSGFREQ0
3840
        ; decay  (16.384 ms)2
3841
        ; attack (8.192 ms)1
3842
        ; release (1.024 s)A
3843
        ; sustain level C
3844
        lda             #0xCA12
3845
        sta             PSGADSR0
3846
        lda             #0x1104                 ; gate, output enable, triangle waveform
3847
        sta             PSGCTRL0
3848
        lda             #1                              ; delay about 10ms
3849
        jsr             Sleep
3850
        lda             #0x0104                 ; gate off, output enable, triangle waveform
3851
        sta             PSGCTRL0
3852
        lda             #1                              ; delay about 10ms
3853
        jsr             Sleep
3854
        lda             #0x0000                 ; gate off, output enable off, no waveform
3855
        sta             PSGCTRL0
3856
        pla
3857
        rts
3858
 
3859
;==============================================================================
3860
;==============================================================================
3861
;
3862 11 robfinch
; Initialize the SD card
3863
; Returns
3864
; acc = 0 if successful, 1 otherwise
3865 26 robfinch
; Z=1 if successful, otherwise Z=0
3866 11 robfinch
;
3867 26 robfinch
message "spi_init"
3868 11 robfinch
spi_init
3869
        lda             #SPI_INIT_SD
3870
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
3871
        lda             #SPI_TRANS_START
3872
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
3873
        nop
3874
spi_init1
3875
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
3876
        nop
3877
        nop
3878
        cmp             #SPI_TRANS_BUSY
3879
        beq             spi_init1
3880
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
3881
        and             #3
3882
        cmp             #SPI_INIT_NO_ERROR
3883
        bne             spi_error
3884 31 robfinch
;       lda             #spi_init_ok_msg
3885
;       jsr             DisplayStringB
3886 11 robfinch
        lda             #0
3887 26 robfinch
        rts
3888 11 robfinch
spi_error
3889
        jsr             DisplayByte
3890 15 robfinch
        lda             #spi_init_error_msg
3891 11 robfinch
        jsr             DisplayStringB
3892
        lda             SPIMASTER+SPI_RESP_BYTE1
3893
        jsr             DisplayByte
3894
        lda             SPIMASTER+SPI_RESP_BYTE2
3895
        jsr             DisplayByte
3896
        lda             SPIMASTER+SPI_RESP_BYTE3
3897
        jsr             DisplayByte
3898
        lda             SPIMASTER+SPI_RESP_BYTE4
3899
        jsr             DisplayByte
3900
        lda             #1
3901
        rts
3902
 
3903 26 robfinch
spi_delay:
3904
        nop
3905
        nop
3906
        rts
3907 11 robfinch
 
3908
 
3909
; SPI read sector
3910
;
3911
; r1= sector number to read
3912
; r2= address to place read data
3913
; Returns:
3914
; r1 = 0 if successful
3915
;
3916
spi_read_sector:
3917
        phx
3918
        phy
3919
        push    r4
3920
 
3921
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
3922 18 robfinch
        lsr             r1,r1,#8
3923 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
3924 18 robfinch
        lsr             r1,r1,#8
3925 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
3926 18 robfinch
        lsr             r1,r1,#8
3927 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
3928
 
3929
        ld              r4,#20  ; retry count
3930
 
3931
spi_read_retry:
3932
        ; Force the reciever fifo to be empty, in case a prior error leaves it
3933
        ; in an unknown state.
3934
        lda             #1
3935
        sta             SPIMASTER+SPI_RX_FIFO_CTRL_REG
3936
 
3937
        lda             #RW_READ_SD_BLOCK
3938
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
3939
        lda             #SPI_TRANS_START
3940
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
3941
        nop
3942
spi_read_sect1:
3943
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
3944 26 robfinch
        jsr             spi_delay                       ; just a delay between consecutive status reg reads
3945 11 robfinch
        cmp             #SPI_TRANS_BUSY
3946
        beq             spi_read_sect1
3947
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
3948
        lsr
3949
        lsr
3950
        and             #3
3951
        cmp             #SPI_READ_NO_ERROR
3952
        bne             spi_read_error
3953
        ldy             #512            ; read 512 bytes from fifo
3954
spi_read_sect2:
3955
        lda             SPIMASTER+SPI_RX_FIFO_DATA_REG
3956 15 robfinch
        sb              r1,0,x
3957 11 robfinch
        inx
3958
        dey
3959
        bne             spi_read_sect2
3960
        lda             #0
3961
        bra             spi_read_ret
3962
spi_read_error:
3963 15 robfinch
        dec             r4
3964 11 robfinch
        bne             spi_read_retry
3965
        jsr             DisplayByte
3966 15 robfinch
        lda             #spi_read_error_msg
3967 11 robfinch
        jsr             DisplayStringB
3968
        lda             #1
3969
spi_read_ret:
3970
        pop             r4
3971
        ply
3972
        plx
3973
        rts
3974
 
3975
; SPI write sector
3976
;
3977
; r1= sector number to write
3978
; r2= address to get data from
3979
; Returns:
3980
; r1 = 0 if successful
3981
;
3982
spi_write_sector:
3983
        phx
3984
        phy
3985
        pha
3986
        ; Force the transmitter fifo to be empty, in case a prior error leaves it
3987
        ; in an unknown state.
3988
        lda             #1
3989
        sta             SPIMASTER+SPI_TX_FIFO_CTRL_REG
3990
        nop                     ; give I/O time to respond
3991
        nop
3992
 
3993
        ; now fill up the transmitter fifo
3994
        ldy             #512
3995
spi_write_sect1:
3996 15 robfinch
        lb              r1,0,x
3997 11 robfinch
        sta             SPIMASTER+SPI_TX_FIFO_DATA_REG
3998
        nop                     ; give the I/O time to respond
3999
        nop
4000
        inx
4001
        dey
4002
        bne             spi_write_sect1
4003
 
4004
        ; set the sector number in the spi master address registers
4005
        pla
4006
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
4007 18 robfinch
        lsr             r1,r1,#8
4008 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
4009 18 robfinch
        lsr             r1,r1,#8
4010 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
4011 18 robfinch
        lsr             r1,r1,#8
4012 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
4013
 
4014
        ; issue the write command
4015
        lda             #RW_WRITE_SD_BLOCK
4016
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
4017
        lda             #SPI_TRANS_START
4018
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
4019
        nop
4020
spi_write_sect2:
4021
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
4022
        nop                                                     ; just a delay between consecutive status reg reads
4023
        nop
4024
        cmp             #SPI_TRANS_BUSY
4025
        beq             spi_write_sect2
4026
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
4027 18 robfinch
        lsr             r1,r1,#4
4028 11 robfinch
        and             #3
4029
        cmp             #SPI_WRITE_NO_ERROR
4030
        bne             spi_write_error
4031
        lda             #0
4032
        bra             spi_write_ret
4033
spi_write_error:
4034
        jsr             DisplayByte
4035 15 robfinch
        lda             #spi_write_error_msg
4036 11 robfinch
        jsr             DisplayStringB
4037
        lda             #1
4038
 
4039
spi_write_ret:
4040
        ply
4041
        plx
4042
        rts
4043
 
4044 31 robfinch
; SPI read multiple sector
4045
;
4046
; r1= sector number to read
4047
; r2= address to write data
4048
; r3= number of sectors to read
4049
;
4050
; Returns:
4051
; r1 = 0 if successful
4052
;
4053
spi_read_multiple:
4054
        push    r4
4055
        ld              r4,#0
4056
spi_rm1:
4057
        pha
4058
        jsr             spi_read_sector
4059
        add             r4,r4,r1
4060
        add             r2,r2,#512
4061
        pla
4062
        ina
4063
        dey
4064
        bne             spi_rm1
4065
        ld              r1,r4
4066
        pop             r4
4067
        rts
4068
 
4069 28 robfinch
; SPI write multiple sector
4070
;
4071
; r1= sector number to write
4072
; r2= address to get data from
4073
; r3= number of sectors to write
4074
;
4075
; Returns:
4076
; r1 = 0 if successful
4077
;
4078
spi_write_multiple:
4079
        push    r4
4080 31 robfinch
        ld              r4,#0
4081 28 robfinch
spi_wm1:
4082
        pha
4083
        jsr             spi_write_sector
4084
        add             r4,r4,r1                ; accumulate an error count
4085
        add             r2,r2,#512              ; 512 bytes per sector
4086
        pla
4087
        ina
4088
        dey
4089
        bne             spi_wm1
4090
        ld              r1,r4
4091
        pop             r4
4092
        rts
4093
 
4094 15 robfinch
; read the partition table to find out where the boot sector is.
4095 26 robfinch
; Returns
4096
; r1 = 0 everything okay, 1=read error
4097
; also Z=1=everything okay, Z=0=read error
4098 15 robfinch
;
4099
spi_read_part:
4100
        phx
4101
        stz             startSector                                             ; default starting sector
4102
        lda             #0                                                              ; r1 = sector number (#0)
4103 26 robfinch
        ldx             #BYTE_SECTOR_BUF                                ; r2 = target address (word to byte address)
4104 15 robfinch
        jsr             spi_read_sector
4105 18 robfinch
        cmp             #0
4106
        bne             spi_rp1
4107 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1C9
4108 18 robfinch
        asl             r1,r1,#8
4109 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C8
4110 18 robfinch
        asl             r1,r1,#8
4111 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C7
4112 18 robfinch
        asl             r1,r1,#8
4113 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C6
4114
        sta             startSector                                             ; r1 = 0, for okay status
4115 18 robfinch
        plx
4116 15 robfinch
        lda             #0
4117 18 robfinch
        rts
4118
spi_rp1:
4119 15 robfinch
        plx
4120 18 robfinch
        lda             #1
4121 15 robfinch
        rts
4122
 
4123
; Read the boot sector from the disk.
4124
; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.
4125 26 robfinch
; Returns:
4126
; r1 = 0 means this card is bootable
4127
; r1 = 1 means a read error occurred
4128
; r1 = 2 means the card is not bootable
4129 15 robfinch
;
4130
spi_read_boot:
4131
        phx
4132
        phy
4133
        push    r5
4134
        lda             startSector                                     ; r1 = sector number
4135
        ldx             #BYTE_SECTOR_BUF                        ; r2 = target address
4136
        jsr             spi_read_sector
4137 26 robfinch
        cmp             #0
4138
        bne             spi_read_boot_err
4139 15 robfinch
        lb              r1,BYTE_SECTOR_BUF
4140
        cmp             #$EB
4141 26 robfinch
        bne             spi_eb_err
4142 15 robfinch
spi_read_boot2:
4143
        lda             #msgFoundEB
4144
        jsr             DisplayStringB
4145
        lb              r1,BYTE_SECTOR_BUF+$1FE         ; check for 0x55AA signature
4146
        cmp             #$55
4147 26 robfinch
        bne             spi_eb_err
4148 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1FF         ; check for 0x55AA signature
4149
        cmp             #$AA
4150 26 robfinch
        bne             spi_eb_err
4151
        pop             r5
4152
        ply
4153
        plx
4154 15 robfinch
        lda             #0                                              ; r1 = 0, for okay status
4155 26 robfinch
        rts
4156
spi_read_boot_err:
4157 15 robfinch
        pop             r5
4158
        ply
4159
        plx
4160 26 robfinch
        lda             #1
4161 15 robfinch
        rts
4162 26 robfinch
spi_eb_err:
4163
        lda             #msgNotFoundEB
4164
        jsr             DisplayStringB
4165
        pop             r5
4166
        ply
4167
        plx
4168
        lda             #2
4169
        rts
4170 15 robfinch
 
4171
msgFoundEB:
4172
        db      "Found EB code.",CR,LF,0
4173 26 robfinch
msgNotFoundEB:
4174
        db      "EB/55AA Code missing.",CR,LF,0
4175 15 robfinch
 
4176
; Load the root directory from disk
4177
; r2 = where to place root directory in memory
4178
;
4179
loadBootFile:
4180 31 robfinch
        lb              r1,BYTE_SECTOR_BUF+BSI_SecPerFAT+1                      ; sectors per FAT
4181 18 robfinch
        asl             r1,r1,#8
4182 31 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+BSI_SecPerFAT
4183 15 robfinch
        bne             loadBootFile7
4184
        lb              r1,BYTE_SECTOR_BUF+$27                  ; sectors per FAT, FAT32
4185 18 robfinch
        asl             r1,r1,#8
4186 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$26
4187 18 robfinch
        asl             r1,r1,#8
4188 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$25
4189 18 robfinch
        asl             r1,r1,#8
4190 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$24
4191
loadBootFile7:
4192
        lb              r4,BYTE_SECTOR_BUF+$10                  ; number of FATs
4193
        mul             r3,r1,r4                                                ; offset
4194
        lb              r1,BYTE_SECTOR_BUF+$F                   ; r1 = # reserved sectors before FAT
4195 18 robfinch
        asl             r1,r1,#8
4196 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$E
4197
        add             r3,r3,r1                                                ; r3 = root directory sector number
4198
        ld              r6,startSector
4199
        add             r5,r3,r6                                                ; r5 = root directory sector number
4200
        lb              r1,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
4201
        add             r3,r1,r5                                                ; r3 = first cluster after first cluster of directory
4202
        bra             loadBootFile6
4203
 
4204
loadBootFile6:
4205
        ; For now we cheat and just go directly to sector 512.
4206
        bra             loadBootFileTmp
4207
 
4208
loadBootFileTmp:
4209
        ; We load the number of sectors per cluster, then load a single cluster of the file.
4210
        ; This is 16kib
4211
        ld              r5,r3                                                   ; r5 = start sector of data area
4212
        ld              r2,#PROG_LOAD_AREA                              ; where to place file in memory
4213
        lb              r3,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
4214
loadBootFile1:
4215
        ld              r1,r5                                                   ; r1=sector to read
4216
        jsr             spi_read_sector
4217
        inc             r5                                              ; r5 = next sector
4218
        add             r2,r2,#512
4219
        dec             r3
4220
        bne             loadBootFile1
4221 26 robfinch
        lda             PROG_LOAD_AREA>>2               ; make sure it's bootable
4222 15 robfinch
        cmp             #$544F4F42
4223
        bne             loadBootFile2
4224
        lda             #msgJumpingToBoot
4225
        jsr             DisplayStringB
4226 26 robfinch
        lda             (PROG_LOAD_AREA>>2)+$1
4227 15 robfinch
        jsr             (r1)
4228
        jmp             Monitor
4229
loadBootFile2:
4230
        lda             #msgNotBootable
4231
        jsr             DisplayStringB
4232
        ldx             #PROG_LOAD_AREA>>2
4233
        jsr             DisplayMemW
4234
        jsr             DisplayMemW
4235
        jsr             DisplayMemW
4236
        jsr             DisplayMemW
4237
        jmp             Monitor
4238
 
4239 11 robfinch
msgJumpingToBoot:
4240
        db      "Jumping to boot",0
4241
msgNotBootable:
4242
        db      "SD card not bootable.",0
4243
spi_init_ok_msg:
4244
        db "SD card initialized okay.",0
4245
spi_init_error_msg:
4246
        db      ": error occurred initializing the SD card.",0
4247
spi_boot_error_msg:
4248 26 robfinch
        db      "SD card boot error",CR,LF,0
4249 11 robfinch
spi_read_error_msg:
4250 26 robfinch
        db      "SD card read error",CR,LF,0
4251 11 robfinch
spi_write_error_msg:
4252
        db      "SD card write error",0
4253
 
4254 31 robfinch
do_fmt:
4255
        jsr             spi_init
4256
        cmp             #0
4257
        bne             fmt_abrt
4258
        ldx             #DIRBUF
4259
        ldy             #65536
4260
        ; clear out the directory buffer
4261
dfmt1:
4262
        stz             (x)
4263
        inx
4264
        dey
4265
        bne             dfmt1
4266
        jsr             store_dir
4267
fmt_abrt:
4268
        rts
4269
 
4270
do_dir:
4271
        jsr             CRLF
4272
        jsr             spi_init
4273
        cmp             #0
4274
        bne             dirabrt
4275
        jsr             load_dir
4276
        ld              r4,#0                   ; r4 = entry counter
4277
ddir3:
4278
        asl             r3,r4,#6                ; y = start of entry, 64 bytes per entry
4279
        ldx             #32                             ; 32 chars in filename
4280
ddir4:
4281
        lb              r1,DIRBUF<<2,y
4282
        beq             ddir2                   ; move to next dir entry if null is found
4283
        cmp             #$20                    ; don't display control chars
4284
        bmi             ddir1
4285
        jsr             DisplayChar
4286
        bra             ddir5
4287
ddir1:
4288
        lda             #' '
4289
        jsr             DisplayChar
4290
ddir5:
4291
        iny
4292
        dex
4293
        bne             ddir4
4294
        lda             #' '
4295
        jsr             DisplayChar
4296
        asl             r3,r4,#4                ; y = start of entry, 16 words per entry
4297
        lda             DIRBUF+$D,y
4298
        ldx             #5
4299
        jsr             PRTNUM
4300
        jsr             CRLF
4301
ddir2:
4302
        jsr             KeybdGetChar
4303
        cmp             #CTRLC
4304
        beq             ddir6
4305
        inc             r4
4306
        cmp             r4,#512         ; max 512 dir entries
4307
        bne             ddir3
4308
ddir6:
4309
 
4310
dirabrt:
4311
        rts
4312
 
4313
load_dir:
4314
        pha
4315
        phx
4316
        phy
4317
        lda             #4000
4318
        ldx             #DIRBUF<<2
4319
        ldy             #64
4320
        jsr             spi_read_multiple
4321
        ply
4322
        plx
4323
        pla
4324
        rts
4325
store_dir:
4326
        pha
4327
        phx
4328
        phy
4329
        lda             #4000
4330
        ldx             #DIRBUF<<2
4331
        ldy             #64
4332
        jsr             spi_write_multiple
4333
        ply
4334
        plx
4335
        pla
4336
        rts
4337
 
4338
; r1 = pointer to file name
4339
; r2 = pointer to buffer to save
4340
; r3 = length of buffer
4341
;
4342
do_save:
4343
        pha
4344
        jsr             spi_init
4345
        cmp             #0
4346
        bne             dsavErr
4347
        pla
4348
        jsr             load_dir
4349
        ld              r4,#0
4350
dsav4:
4351
        asl             r5,r4,#6
4352
        ld              r7,#0
4353
        ld              r10,r1
4354
dsav2:
4355
        lb              r6,DIRBUF<<2,r5
4356
        lb              r8,0,r10
4357
        cmp             r6,r8
4358
        bne             dsav1
4359
        inc             r5
4360
        inc             r7
4361
        inc             r10
4362
        cmp             r7,#32
4363
        bne             dsav2
4364
        ; here the filename matched
4365
dsav8:
4366
        asl             r7,r4,#7        ; compute file address  64k * entry #
4367
        add             r7,r7,#5000     ; start at sector 5,000
4368
        ld              r1,r7           ; r1 = sector number
4369
        lsr             r3,r3,#9        ; r3/512
4370
        iny                                     ; +1
4371
        jsr             spi_write_multiple
4372
dsav3:
4373
        rts
4374
        ; Here the filename didn't match
4375
dsav1:
4376
        inc             r4
4377
        cmp             r4,#512
4378
        bne             dsav4
4379
        ; Here none of the filenames in the directory matched
4380
        ; Find an empty entry.
4381
        ld              r4,#0
4382
dsav6:
4383
        asl             r5,r4,#6
4384
        lb              r6,DIRBUF<<2,r5
4385
        beq             dsav5
4386
        inc             r4
4387
        cmp             r4,#512
4388
        bne             dsav6
4389
        ; Here there were no empty entries
4390
        lda             #msgDiskFull
4391
        jsr             DisplayStringB
4392
        rts
4393
dsav5:
4394
        ld              r7,#32
4395
        ld              r10,r1
4396
dsav7:
4397
        lb              r6,0,r10        ; copy the filename into the directory entry
4398
        sb              r6,DIRBUF<<2,r5
4399
        inc             r5
4400
        inc             r10
4401
        dec             r7
4402
        bne             dsav7
4403
                                                ; copy the file size into the directory entry
4404
        asl             r5,r4,#4        ; 16 words per dir entry
4405
        sty             DIRBUF+$D,r5
4406
        jsr             store_dir
4407
        bra             dsav8
4408
dsavErr:
4409
        pla
4410
        rts
4411
 
4412
msgDiskFull
4413
        db      CR,LF,"The disk is full, unable to save file.",CR,LF,0
4414
 
4415
do_load:
4416
        pha
4417
        jsr             spi_init
4418
        cmp             #0
4419
        bne             dsavErr
4420
        pla
4421
        jsr             load_dir
4422
        ld              r4,#0
4423
dlod4:
4424
        asl             r5,r4,#6
4425
        ld              r7,#0
4426
        ld              r10,r1
4427
dlod2:
4428
        lb              r6,DIRBUF<<2,r5
4429
        lb              r8,0,r10
4430
        cmp             r6,r8
4431
        bne             dlod1
4432
        inc             r5
4433
        inc             r7
4434
        inc             r10
4435
        cmp             r7,#32
4436
        bne             dlod2
4437
        ; here the filename matched
4438
dlod8:
4439
        asl             r5,r4,#4                                ; 16 words
4440
        ld              r3,DIRBUF+$d,r5                 ; get file size into y register
4441
        asl             r7,r4,#7        ; compute file address  64k * entry #
4442
        add             r7,r7,#5000     ; start at sector 5,000
4443
        ld              r1,r7           ; r1 = sector number
4444
        lsr             r3,r3,#9        ; r3/512
4445
        iny                                     ; +1
4446
        jsr             spi_read_multiple
4447
dlod3:
4448
        rts
4449
        ; Here the filename didn't match
4450
dlod1:
4451
        inc             r4
4452
        cmp             r4,#512
4453
        bne             dlod4
4454
        ; Here none of the filenames in the directory matched
4455
        ;
4456
        lda             #msgFileNotFound
4457
        jsr             DisplayStringB
4458
        rts
4459
 
4460
msgFileNotFound:
4461
        db      CR,LF,"File not found.",CR,LF
4462
 
4463 26 robfinch
;==============================================================================
4464
; Ethernet
4465
;==============================================================================
4466
my_MAC1 EQU     0x00
4467
my_MAC2 EQU     0xFF
4468
my_MAC3 EQU     0xEE
4469
my_MAC4 EQU     0xF0
4470
my_MAC5 EQU     0xDA
4471
my_MAC6 EQU     0x42
4472
 
4473
; Initialize the ethmac controller.
4474
; Supply a MAC address, set MD clock
4475
;
4476
message "eth_init"
4477
eth_init:
4478
        pha
4479
        phy
4480
        ldy             #ETHMAC
4481
        lda             #0x64                           ; 100
4482
        sta             ETH_MIIMODER,y
4483
        lda             #7                                      ; PHY address
4484
        sta             ETH_MIIADDRESS,y
4485
        lda             #0xEEF0DA42
4486
        sta             ETH_MAC_ADDR0,y         ; MAC0
4487
        lda             #0x00FF
4488
        sta             ETH_MAC_ADDR1,y         ; MAC1
4489
        ply
4490
        pla
4491
        rts
4492
 
4493
; Request a packet and display on screen
4494
; r1 = address where to put packet
4495
;
4496
message "eth_request_packet"
4497
eth_request_packet:
4498
        phx
4499
        phy
4500
        push    r4
4501
        push    r5
4502
        ldy             #ETHMAC
4503
        ldx             #4                                      ; clear rx interrupt
4504
        stx             ETH_INT_SOURCE,y
4505
        sta             0x181,y                         ; storage address
4506
        ldx             #0xe000                         ; enable interrupt
4507
        stx             0x180,y
4508
eth1:
4509
        nop
4510
        ldx             ETH_INT_SOURCE,y
4511
        and             r2,r2,#4                        ; get bit #2
4512
        beq             eth1
4513
        ldx             0x180,y                         ; get from descriptor
4514
        lsr             r2,r2,#16
4515
        ldy             #0
4516
        ld              r4,#TEXTSCR+3780        ; second last line of screen
4517
eth20:
4518
        add             r5,r1,r3
4519
        ldx             (r5)                            ; get byte
4520
        add             r5,r4,r3
4521
        stx             (r5)                            ; store to screen
4522
        iny
4523
        cpy             #83
4524
        bne             eth20
4525
        pop             r5
4526
        pop             r4
4527
        ply
4528
        plx
4529
        rts
4530
 
4531
; r1 = packet address
4532
;
4533
message "eth_interpret_packet"
4534
eth_interpret_packet:
4535
        phx
4536
        phy
4537
        lb              r2,12,r1
4538
        lb              r3,13,r1
4539
        cpx             #8                                      ; 0x806 ?
4540
        bne             eth2
4541
        cpy             #6
4542
        bne             eth2
4543
        lda             #2                                      ; return r1 = 2 for ARP
4544
eth5:
4545
        ply
4546
        plx
4547
        rts
4548
eth2:
4549
        cpx             #8
4550
        bne             eth3                            ; 0x800 ?
4551
        cpy             #0
4552
        bne             eth3
4553
        lb              r2,23,r1
4554
        cpx             #1
4555
        bne             eth4
4556
        lda             #1
4557
        bra             eth5                            ; return 1 ICMP
4558
eth4:
4559
        cpx             #$11
4560
        bne             eth6
4561
        lda             #3                                      ; return 3 for UDP
4562
        bra             eth5
4563
eth6:
4564
        cpx             #6
4565
        bne             eth7
4566
        lda             #4                                      ; return 4 for TCP
4567
        bra             eth5
4568
eth7:
4569
eth3:
4570
        eor             r1,r1,r1                        ; return zero for unknown
4571
        ply
4572
        plx
4573
        rts
4574
 
4575
; r1 = address of packet to send
4576
; r2 = packet length
4577
;
4578
message "eth_send_packet"
4579
eth_send_packet:
4580
        phx
4581
        phy
4582
        push    r4
4583
        ldy             #ETHMAC
4584
        ; wait for tx buffer to be clear
4585
eth8:
4586
        ld              r4,0x100,y
4587
        and             r4,r4,#$8000
4588
        bne             eth8
4589
        ld              r4,#1                   ; clear tx interrupt
4590
        st              r4,ETH_INT_SOURCE,y
4591
        ; set address
4592
        sta             0x101,y
4593
        ; set the packet length field and enable interrupts
4594
        asl             r2,r2,#16
4595
        or              r2,r2,#0xF000
4596
        stx             0x100,y
4597
        pop             r4
4598
        ply
4599
        plx
4600
        rts
4601
 
4602
; Only for IP type packets (not ARP)
4603
; r1 = rx buffer address
4604
; r2 = swap flag
4605
; Returns:
4606
; r1 = data start index
4607
;
4608
message "eth_build_packet"
4609
eth_build_packet:
4610
        phy
4611
        push    r4
4612
        push    r5
4613
        push    r6
4614
        push    r7
4615
        push    r8
4616
        push    r9
4617
        push    r10
4618
 
4619
        lb              r3,6,r1
4620
        lb              r4,7,r1
4621
        lb              r5,8,r1
4622
        lb              r6,9,r1
4623
        lb              r7,10,r1
4624
        lb              r8,11,r1
4625
        ; write to destination header
4626
        sb              r3,0,r1
4627
        sb              r4,1,r1
4628
        sb              r5,2,r1
4629
        sb              r6,3,r1
4630
        sb              r7,4,r1
4631
        sb              r8,5,r1
4632
        ; write to source header
4633
        ld              r3,#my_MAC1
4634
        sb              r3,6,r1
4635
        ld              r3,#my_MAC2
4636
        sb              r3,7,r1
4637
        ld              r3,#my_MAC3
4638
        sb              r3,8,r1
4639
        ld              r3,#my_MAC4
4640
        sb              r3,9,r1
4641
        ld              r3,#my_MAC5
4642
        sb              r3,10,r1
4643
        ld              r3,#my_MAC6
4644
        sb              r3,11,r1
4645
        cmp             r2,#1
4646
        bne             eth16                   ; if (swap)
4647
        lb              r3,26,r1
4648
        lb              r4,27,r1
4649
        lb              r5,28,r1
4650
        lb              r6,29,r1
4651
        ; read destination
4652
        lb              r7,30,r1
4653
        lb              r8,31,r1
4654
        lb              r9,32,r1
4655
        lb              r10,33,r1
4656
        ; write to sender
4657
        sb              r7,26,r1
4658
        sb              r8,27,r1
4659
        sb              r9,28,r1
4660
        sb              r10,29,r1
4661
        ; write destination
4662
        sb              r3,30,r1
4663
        sb              r4,31,r1
4664
        sb              r5,32,r1
4665
        sb              r6,33,r1
4666
eth16:
4667
        ldy             eth_unique_id
4668
        iny
4669
        sty             eth_unique_id
4670
        sb              r3,19,r1
4671
        lsr             r3,r3,#8
4672
        sb              r3,18,r1
4673
        lb              r3,14,r1
4674
        and             r3,r3,#0xF
4675
        asl             r3,r3,#2                ; *4
4676
        add             r1,r3,#14               ; return datastart in r1
4677
        pop             r10
4678
        pop             r9
4679
        pop             r8
4680
        pop             r7
4681
        pop             r6
4682
        pop             r5
4683
        pop             r4
4684
        ply
4685
        rts
4686
 
4687
; Compute IPv4 checksum of header
4688
; r1 = packet address
4689
; r2 = data start
4690
;
4691
message "eth_checksum"
4692
eth_checksum:
4693
        phy
4694
        push    r4
4695
        push    r5
4696
        push    r6
4697
        ; set checksum to zero
4698
        stz             24,r1
4699
        stz             25,r1
4700
        eor             r3,r3,r3                ; r3 = sum = zero
4701
        ld              r4,#14
4702
eth15:
4703
        ld              r5,r2
4704
        dec             r5                              ; r5 = datastart - 1
4705
        cmp             r4,r5
4706
        bpl             eth14
4707
        add             r6,r1,r4
4708
        lb              r5,0,r6                 ; shi = [rx_addr+i]
4709
        lb              r6,1,r6             ; slo = [rx_addr+i+1]
4710
        asl     r5,r5,#8
4711
        or              r5,r5,r6                ; shilo
4712
        add             r3,r3,r5                ; sum = sum + shilo
4713
        add             r4,r4,#2                ; i = i + 2
4714
        bra             eth15
4715
eth14:
4716
        ld              r5,r3                   ; r5 = sum
4717
        and             r3,r3,#0xffff
4718
        lsr             r5,r5,#16
4719
        add             r3,r3,r5
4720
        eor             r3,r3,#-1
4721
        sb              r3,25,r1                ; low byte
4722
        lsr             r3,r3,#8
4723
        sb              r3,24,r1                ; high byte
4724
        pop             r6
4725
        pop             r5
4726
        pop             r4
4727
        ply
4728
        rts
4729
 
4730
; r1 = packet address
4731
; returns r1 = 1 if this IP
4732
;
4733
message "eth_verifyIP"
4734
eth_verifyIP:
4735
        phx
4736
        phy
4737
        push    r4
4738
        push    r5
4739
        lb              r2,30,r1
4740
        lb              r3,31,r1
4741
        lb              r4,32,r1
4742
        lb              r5,33,r1
4743
        ; Check for general broadcast
4744
        cmp             r2,#$FF
4745
        bne             eth11
4746
        cmp             r3,#$FF
4747
        bne             eth11
4748
        cmp             r4,#$FF
4749
        bne             eth11
4750
        cmp             r5,#$FF
4751
        bne             eth11
4752
eth12:
4753
        lda             #1
4754
eth13:
4755
        pop             r5
4756
        pop             r4
4757
        ply
4758
        plx
4759
        rts
4760
eth11:
4761
        ld              r1,r2
4762
        asl             r1,r1,#8
4763
        or              r1,r1,r3
4764
        asl             r1,r1,#8
4765
        or              r1,r1,r4
4766
        asl             r1,r1,#8
4767
        or              r1,r1,r5
4768
        cmp             #$C0A8012A              ; 192.168.1.42
4769
        beq             eth12
4770
        eor             r1,r1,r1
4771
        bra             eth13
4772
 
4773
message "eth_main"
4774
eth_main:
4775
        jsr             eth_init
4776
eth_loop:
4777
        jsr             KeybdGetChar
4778
        cmp             #-1
4779
        beq             eth17
4780
        cmp             #CTRLC
4781
        bne             eth17
4782
        rts
4783
eth17
4784
        lda             #eth_rx_buffer<<2               ; memory address zero
4785
        jsr             eth_request_packet
4786
        jsr             eth_interpret_packet    ; r1 = packet type
4787
 
4788
        cmp             #1
4789
        bne             eth10
4790
        ld              r2,r1                                   ; save off r1, r2 = packet type
4791
        lda             #eth_rx_buffer<<2               ; memory address zero
4792
        jsr             eth_verifyIP
4793
        tay
4794
        txa                                                             ; r1 = packet type again
4795
        cpy             #1
4796
        bne             eth10
4797
 
4798
        lda             #eth_rx_buffer<<2               ; memory address zero
4799
        ldx             #1
4800
        jsr             eth_build_packet
4801
        tay                                                             ; y = icmpstart
4802
        lda             #eth_rx_buffer<<2               ; memory address zero
4803
        add             r4,r1,r3
4804
        sb              r0,0,r4                                 ; [rx_addr+icmpstart] = 0
4805
        lb              r2,17,r1
4806
        add             r2,r2,#14                               ; r2 = len
4807
        ld              r6,r2                                   ; r6 = len
4808
        add             r15,r1,r3
4809
        lb              r4,2,r15                                ; shi
4810
        lb              r5,3,r15                                ; slo
4811
        asl             r4,r4,#8
4812
        or              r4,r4,r5                                ; sum = {shi,slo};
4813
        eor             r4,r4,#-1                               ; sum = ~sum
4814
        sub             r4,r4,#0x800                    ; sum = sum - 0x800
4815
        eor             r4,r4,#-1                               ; sum = ~sum
4816
        add             r15,r1,r3
4817
        sb              r4,3,r15
4818
        lsr             r4,r4,#8
4819
        sb              r4,2,r15
4820
        tyx
4821
        jsr             eth_checksum
4822
        lda             #eth_rx_buffer<<2               ; memory address zero
4823
        ld              r2,r6
4824
        jsr             eth_send_packet
4825
        jmp             eth_loop
4826
eth10:
4827
        ; r2 = rx_addr
4828
        cmp             #2
4829
        bne             eth_loop                ; Do we have ARP ?
4830
;       xor             r2,r2,r2                        ; memory address zero
4831
        ldx             #eth_rx_buffer<<2
4832
        ; get the opcode
4833
        lb              r13,21,x
4834
        cmp             r13,#1
4835
        bne             eth_loop                ; ARP request
4836
        ; get destination IP address
4837
        lb              r9,38,x
4838
        lb              r10,39,x
4839
        lb              r11,40,x
4840
        lb              r12,41,x
4841
        ; set r15 = destination IP
4842
        ld              r15,r9
4843
        asl             r15,r15,#8
4844
        or              r15,r15,r10
4845
        asl             r15,r15,#8
4846
        or              r15,r15,r11
4847
        asl             r15,r15,#8
4848
        or              r15,r15,r12
4849
        ; Is it our IP ?
4850
        cmp             r15,#$C0A8012A  ; //192.168.1.42
4851
        bne             eth_loop
4852
        ; get source IP address
4853
        lb              r5,28,x
4854
        lb              r6,29,x
4855
        lb              r7,30,x
4856
        lb              r8,31,x
4857
        ; set r14 = source IP
4858
        ld              r14,r5
4859
        asl             r14,r14,#8
4860
        or              r14,r14,r6
4861
        asl             r14,r14,#8
4862
        or              r14,r14,r7
4863
        asl             r14,r14,#8
4864
        or              r14,r14,r8
4865
        ; Get the source MAC address
4866
        push    r6
4867
        push    r7
4868
        push    r8
4869
        push    r9
4870
        push    r10
4871
        push    r11
4872
        lb              r6,22,x
4873
        lb              r7,23,x
4874
        lb              r8,24,x
4875
        lb              r9,25,x
4876
        lb              r10,26,x
4877
        lb              r11,27,x
4878
        ; write to destination header
4879
        sb              r6,0,x
4880
        sb              r7,1,x
4881
        sb              r8,2,x
4882
        sb              r9,3,x
4883
        sb              r10,4,x
4884
        sb              r11,5,x
4885
        ; and write to ARP destination
4886
        sb              r6,32,x
4887
        sb              r7,33,x
4888
        sb              r8,34,x
4889
        sb              r9,35,x
4890
        sb              r10,36,x
4891
        sb              r11,37,x
4892
        pop             r11
4893
        pop             r10
4894
        pop             r9
4895
        pop             r8
4896
        pop             r7
4897
        pop             r6
4898
        ; write to source header
4899
;       stbc    #0x00,6[r2]
4900
;       stbc    #0xFF,7[r2]
4901
;       stbc    #0xEE,8[r2]
4902
;       stbc    #0xF0,9[r2]
4903
;       stbc    #0xDA,10[r2]
4904
;       stbc    #0x42,11[r2]
4905
        sb              r0,6,x
4906
        lda             #0xFF
4907
        sb              r1,7,x
4908
        lda             #0xEE
4909
        sb              r1,8,x
4910
        lda             #0xF0
4911
        sb              r1,9,x
4912
        lda             #0xDA
4913
        sb              r1,10,x
4914
        lda             #0x42
4915
        sb              r1,11,x
4916
        ; write to ARP source
4917
;       stbc    #0x00,22[r2]
4918
;       stbc    #0xFF,23[r2]
4919
;       stbc    #0xEE,24[r2]
4920
;       stbc    #0xF0,25[r2]
4921
;       stbc    #0xDA,26[r2]
4922
;       stbc    #0x42,27[r2]
4923
        sb              r0,22,x
4924
        lda             #0xFF
4925
        sb              r1,23,x
4926
        lda             #0xEE
4927
        sb              r1,24,x
4928
        lda             #0xF0
4929
        sb              r1,25,x
4930
        lda             #0xDA
4931
        sb              r1,26,x
4932
        lda             #0x42
4933
        sb              r1,27,x
4934
        ; swap sender / destination IP
4935
        ; write sender
4936
        sb              r9,28,x
4937
        sb              r10,29,x
4938
        sb              r11,30,x
4939
        sb              r12,31,x
4940
        ; write destination
4941
        sb              r5,38,x
4942
        sb              r6,39,x
4943
        sb              r7,40,x
4944
        sb              r8,41,x
4945
        ; change request to reply
4946
;       stbc    #2,21[r2]
4947
        lda             #2
4948
        sb              r1,21,x
4949
        txa                                             ; r1 = packet address
4950
        ldx             #0x2A                   ; r2 = packet length
4951
        jsr             eth_send_packet
4952
        jmp             eth_loop
4953
 
4954
;--------------------------------------------------------------------------
4955
; Initialize sprite image caches with random data.
4956
;--------------------------------------------------------------------------
4957
RandomizeSprram:
4958
        ldx             #SPRRAM
4959
        ld              r4,#14336               ; number of chars to initialize
4960
rsr1:
4961
        tsr             LFSR,r1
4962
        sta             (x)
4963
        inx
4964
        dec             r4
4965
        bne             rsr1
4966
        rts
4967
 
4968
;--------------------------------------------------------------------------
4969
; Draw random lines on the bitmap screen.
4970
;--------------------------------------------------------------------------
4971
;
4972
RandomLines:
4973
        pha
4974
        phx
4975
        phy
4976
        push    r4
4977
        push    r5
4978
        jsr             RequestIOFocus
4979
rl5:
4980
        tsr             LFSR,r1
4981
        tsr             LFSR,r2
4982
        jsr             DrawPixel
4983
        tsr             LFSR,r1
4984
        sta             LineColor               ; select a random color
4985
rl1:                                            ; random X0
4986
        tsr             LFSR,r1
4987
        ld              r5,#1364
4988
        mod             r1,r1,r5
4989
rl2:                                            ; random X1
4990
        tsr             LFSR,r3
4991
        mod             r3,r3,r5
4992
rl3:                                            ; random Y0
4993
        tsr             LFSR,r2
4994
        ld              r5,#768
4995
        mod             r2,r2,r5
4996
rl4:                                            ; random Y1
4997
        tsr             LFSR,r4
4998
        ld              r5,#768
4999
        mod             r4,r4,r5
5000
rl8:
5001
        jsr             DrawLine
5002
        jsr             KeybdGetChar
5003
        cmp             #CTRLC
5004
        beq             rl7
5005
        bra             rl5
5006
rl7:
5007
        jsr             ReleaseIOFocus
5008
        pop             r5
5009
        pop             r4
5010
        ply
5011
        plx
5012
        pla
5013
        rts
5014
 
5015 28 robfinch
;--------------------------------------------------------------------------
5016
; Draw a pixel on the bitmap screen.
5017
; r1 = x coordinate
5018
; r2 = y coordinate
5019
; r3 = color
5020
;--------------------------------------------------------------------------
5021 26 robfinch
DrawPixel:
5022
        pha
5023
        phx
5024
        push    r4
5025
        ld              r4,#768
5026
        mod             r2,r2,r4
5027
        ld              r4,#1364
5028
        mod             r1,r1,r4
5029
        mul             r2,r2,r4        ; y * 1364
5030
        add             r1,r1,r2        ; + x
5031
        sb              r3,BITMAPSCR<<2,r1
5032
        pop             r4
5033
        plx
5034
        pla
5035
        rts
5036 28 robfinch
 
5037
;--------------------------------------------------------------------------
5038
; Draw a line on the bitmap screen.
5039
;--------------------------------------------------------------------------
5040 26 robfinch
;50 REM DRAWLINE
5041
;100 dx = ABS(xb-xa)
5042
;110 dy = ABS(yb-ya)
5043
;120 sx = SGN(xb-xa)
5044
;130 sy = SGN(yb-ya)
5045
;140 er = dx-dy
5046
;150 PLOT xa,ya
5047
;160 if xa<>xb goto 200
5048
;170 if ya=yb goto 300
5049
;200 ee = er * 2
5050
;210 if ee <= -dy goto 240
5051
;220 er = er - dy
5052
;230 xa = xa + sx
5053
;240 if ee >= dx goto 270
5054
;250 er = er + dx
5055
;260 ya = ya + sy
5056
;270 GOTO 150
5057
;300 RETURN
5058
 
5059
DrawLine:
5060
        pha
5061
        phx
5062
        phy
5063
        push    r4
5064
        push    r5
5065
        push    r6
5066
        push    r7
5067
        push    r8
5068
        push    r9
5069
        push    r10
5070
        push    r11
5071
 
5072
        sub             r5,r3,r1        ; dx = abs(x2-x1)
5073
        bpl             dln1
5074
        sub             r5,r0,r5
5075
dln1:
5076
        sub             r6,r4,r2        ; dy = abs(y2-y1)
5077
        bpl             dln2
5078
        sub             r6,r0,r6
5079
dln2:
5080
 
5081
        sub             r7,r3,r1        ; sx = sgn(x2-x1)
5082
        beq             dln5
5083
        bpl             dln4
5084
        ld              r7,#-1
5085
        bra             dln5
5086
dln4:
5087
        ld              r7,#1
5088
dln5:
5089
 
5090
        sub             r8,r4,r2        ; sy = sgn(y2-y1)
5091
        beq             dln8
5092
        bpl             dln7
5093
        ld              r8,#-1
5094
        bra             dln8
5095
dln7:
5096
        ld              r8,#1
5097
 
5098
dln8:
5099
        sub             r9,r5,r6        ; er = dx-dy
5100
dln150:
5101 28 robfinch
        phy
5102
        ldy             LineColor
5103 26 robfinch
        jsr             DrawPixel
5104 28 robfinch
        ply
5105 26 robfinch
        cmp             r1,r3           ; if (xa <> xb)
5106
        bne             dln200          ;    goto 200
5107
        cmp             r2,r4           ; if (ya==yb)
5108
        beq             dln300          ;    goto 300
5109
dln200:
5110
        asl             r10,r9          ; ee = er * 2
5111
        sub             r11,r0,r6       ; r11 = -dy
5112
        cmp             r10,r11         ; if (ee <= -dy)
5113
        bmi             dln240          ;     goto 240
5114
        beq             dln240
5115
        sub             r9,r9,r6        ; er = er - dy
5116
        add             r1,r1,r7        ; xa = xa + sx
5117
dln240:
5118
        cmp             r10,r5          ; if (ee >= dx)
5119
        bpl             dln150          ;    goto 150
5120
        add             r9,r9,r5        ; er = er + dx
5121
        add             r2,r2,r8        ; ya = ya + sy
5122
        bra             dln150          ; goto 150
5123
 
5124
dln300:
5125
        pop             r11
5126
        pop             r10
5127
        pop             r9
5128
        pop             r8
5129
        pop             r7
5130
        pop             r6
5131
        pop             r5
5132
        pop             r4
5133
        ply
5134
        plx
5135
        pla
5136
        rts
5137
 
5138
;include "float.asm"
5139
 
5140 31 robfinch
 
5141
;==============================================================================
5142
; Memory Management routines follow.
5143
;==============================================================================
5144
MemInit:
5145
        lda             #1                                      ; initialize memory semaphore
5146
        sta             MEM_SEMA
5147
        lda             #$4D454D20
5148
        sta             HeapStart+MEM_CHK
5149
        sta             HeapStart+MEM_FLAG
5150
        sta             HeapEnd-2
5151
        sta             HeapEnd-3
5152
        lda             #0
5153
        sta             HeapStart+MEM_PREV      ; prev of first MEMHDR
5154
        sta             HeapEnd                 ; next of last MEMHDR
5155
        lda             #HeapEnd
5156
        ina
5157
        sub             #$4
5158
        sta             HeapStart+MEM_NEXT      ; next of first MEMHDR
5159
        lda             #HeapStart
5160
        sta             HeapEnd-1               ; prev of last MEMHDR
5161
        rts
5162
 
5163
ReportMemFree:
5164
        jsr             CRLF
5165
        lda             #HeapEnd
5166
        ina
5167
        sub             #HeapStart
5168
        ldx             #5
5169
        jsr             PRTNUM
5170
        lda             #msgMemFree
5171
        jsr             DisplayStringB
5172
        rts
5173
 
5174
msgMemFree:
5175
        db      " words free",CR,LF,0
5176
 
5177 15 robfinch
;------------------------------------------------------------------------------
5178 31 robfinch
; Allocate memory from the heap.
5179
;------------------------------------------------------------------------------
5180
MemAlloc:
5181
        phx
5182
        phy
5183
        push    r4
5184
memaSpin:
5185
        ldx             MEM_SEMA+1
5186
        beq             memaSpin
5187
        ldx             #HeapStart
5188
mema4:
5189
        ldy             MEM_FLAG,x              ; Check the flag word to see if this block is available
5190
        cpy             #$4D454D20
5191
        bne             mema1                   ; block not available, go to next block
5192
        ld              r4,MEM_NEXT,x   ; compute the size of this block
5193
        sub             r4,r4,r2
5194
        sub             r4,r4,#4                ; minus size of block header
5195
        cmp             r1,r4                   ; is the block large enough ?
5196
        bmi             mema2                   ; if yes, go allocate
5197
mema1:
5198
        ldx             MEM_NEXT,x              ; go to the next block
5199
        beq             mema3                   ; if no more blocks, out of memory error
5200
        bra             mema4
5201
mema2:
5202
        ldy             #$6D656D20
5203
        sty             MEM_FLAG,x
5204
        sub             r4,r4,r1
5205
        cmp             r4,#4                   ; is the block large enough to split
5206
        bpl             memaSplit
5207
        stz             MEM_SEMA+1
5208
        txa
5209
        pop             r4
5210
        ply
5211
        plx
5212
        rts
5213
mema3:                                          ; insufficient memory
5214
        stz             MEM_SEMA+1
5215
        pop             r4
5216
        ply
5217
        plx
5218
        lda             #0
5219
        rts
5220
memaSplit:
5221
        add             r4,r1,r2
5222
        add             r4,r4,#4
5223
        ldy             #$4D454D20
5224
        sty             (r4)
5225
        sty             MEM_FLAG,r4
5226
        stx             MEM_PREV,r4
5227
        ldy             MEM_NEXT,x
5228
        sty             MEM_NEXT,r4
5229
        st              r4,MEM_PREV,y
5230
        ld              r1,r4
5231
        stz             MEM_SEMA+1
5232
        pop             r4
5233
        ply
5234
        plx
5235
        rts
5236
 
5237
;------------------------------------------------------------------------------
5238
; Free previously allocated memory. Recombine with next and previous blocks
5239
; if they are free as well.
5240
;------------------------------------------------------------------------------
5241
MemFree:
5242
        cmp             #0                      ; null pointer ?
5243
        beq             memf2
5244
        phx
5245
        phy
5246
memfSpin:
5247
        ldx             MEM_SEMA+1
5248
        beq             memfSpin
5249
        ldx             MEM_FLAG,r1
5250
        cpx             #$6D656D20      ; is the block allocated ?
5251
        bne             memf1
5252
        ldx             #$4D454D20
5253
        stx             MEM_FLAG,r1     ; mark block as free
5254
        ldx             MEM_PREV,r1     ; is the previous block free ?
5255
        beq             memf3           ; no previous block
5256
        ldy             MEM_FLAG,x
5257
        cpy             #$4D454D20
5258
        bne             memf3           ; the previous block is not free
5259
        ldy             MEM_NEXT,r1
5260
        sty             MEM_NEXT,x
5261
        beq             memf1           ; no next block
5262
        stx             MEM_PREV,y
5263
memf3:
5264
        ldy             MEM_NEXT,r1
5265
        ldx             MEM_FLAG,y
5266
        cpx             #$4D454D20
5267
        bne             memf1           ; next block not free
5268
        ldx             MEM_PREV,r1
5269
        stx             MEM_PREV,y
5270
        beq             memf1           ; no previous block
5271
        sty             MEM_NEXT,x
5272
memf1:
5273
        stz             MEM_SEMA+1
5274
        ply
5275
        plx
5276
memf2:
5277
        rts
5278
 
5279
;------------------------------------------------------------------------------
5280 26 robfinch
; Bus Error Routine
5281
; This routine display a message then restarts the BIOS.
5282
;------------------------------------------------------------------------------
5283
;
5284
message "bus_err_rout"
5285
bus_err_rout:
5286
        cld
5287
        pla                                                     ; get rid of the stacked flags
5288
        ply                                                     ; get the error PC
5289
        ldx             #$05FFFFF8                      ; setup stack pointer top of memory
5290
        txs
5291
        jsr             CRLF
5292
        lda             #msgBusErr
5293
        jsr             DisplayStringB
5294
        tya
5295
        jsr             DisplayWord                     ; display the originating PC address
5296
        lda             #msgDataAddr
5297
        jsr             DisplayStringB
5298
        tsr             #9,r1
5299
        jsr             DisplayWord
5300
        cli                                                     ; enable interrupts so we can get a char
5301 28 robfinch
ber1:
5302 26 robfinch
        jsr             KeybdGetChar
5303 28 robfinch
        cmp             #-1
5304
        beq             ber1
5305 31 robfinch
        jmp             ber1
5306 26 robfinch
 
5307
msgBusErr:
5308
        db              "Bus error at: ",0
5309
msgDataAddr:
5310
        db              " data address: ",0
5311
 
5312
strStartQue:
5313
        db              1,0,0,0,2,0,0,0,3,1,0,0,4,0,0,0
5314 31 robfinch
;       db              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5315 26 robfinch
 
5316
;------------------------------------------------------------------------------
5317 15 robfinch
; 100 Hz interrupt
5318
; - takes care of "flashing" the cursor
5319 26 robfinch
; - switching tasks
5320 15 robfinch
;------------------------------------------------------------------------------
5321
;
5322
p100Hz:
5323 26 robfinch
        ; Handle every other interrupt because 100Hz interrupts may be too fast.
5324
        pha
5325 31 robfinch
        lda             #3                              ; reset the edge sense circuit
5326
        sta             PIC_RSTE
5327
;       inc             TEXTSCR+83              ; update IRQ live indicator on screen
5328 26 robfinch
        lda             IRQFlag
5329
        ina
5330
        sta             IRQFlag
5331
        ror
5332
        bcc             p100Hz11
5333
        pla
5334
        rti
5335
 
5336
p100Hz11:
5337
 
5338
        cld             ; clear extended precision mode
5339
 
5340
        ; save off regs on the stack
5341
        phx
5342
        phy
5343
        push    r4
5344
        push    r5
5345
        push    r6
5346
        push    r7
5347
        push    r8
5348
        push    r9
5349
        push    r10
5350
        push    r11
5351
        push    r12
5352
        push    r13
5353
        push    r14
5354
        push    r15
5355
        ldx             RunningTCB
5356
        tsa                                             ; save off the stack pointer
5357
        sta             TCB_SPSave,x
5358
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
5359
        sta             TCB_SP8Save,x
5360 31 robfinch
        tsr             abs8,r1
5361
        sta             TCB_ABS8Save,x  ; 8 bit emulation base register
5362 28 robfinch
        lda             TCB_Status,x    ; set the task status to PREEMPT
5363
        and             r1,r1,#~TS_RUNNING
5364
        or              r1,r1,#TS_PREEMPT
5365
        sta             TCB_Status,x
5366 31 robfinch
p100Hz4:
5367 26 robfinch
 
5368
        ; support EhBASIC's IRQ functionality
5369
        ; code derived from minimon.asm
5370
        lda             #3                              ; Timer is IRQ #3
5371
        sta             IrqSource               ; stuff a byte indicating the IRQ source for PEEK()
5372
        lb              r1,IrqBase              ; get the IRQ flag byte
5373 31 robfinch
        lsr             r4,r1
5374
        or              r1,r1,r4
5375 26 robfinch
        and             #$E0
5376
        sb              r1,IrqBase
5377
 
5378
        inc             TEXTSCR+83              ; update IRQ live indicator on screen
5379
 
5380
        ; flash the cursor
5381 31 robfinch
        cpx             IOFocusNdx              ; only flash the cursor for the task with the IO focus.
5382
        bne             p100Hz1a
5383 26 robfinch
        lda             CursorFlash             ; test if we want a flashing cursor
5384
        beq             p100Hz1a
5385
        jsr             CalcScreenLoc   ; compute cursor location in memory
5386
        tay
5387
        lda             $10000,y                ; get color code $10000 higher in memory
5388 31 robfinch
        ld              r4,IRQFlag              ; get counter
5389
        lsr             r4,r4
5390
        and             r4,r4,#$0F              ; limit to low order nybble
5391 26 robfinch
        and             #$F0                    ; prepare to or in new value, mask off foreground color
5392 31 robfinch
        or              r1,r1,r4                ; set new foreground color for cursor
5393 26 robfinch
        sta             $10000,y                ; store the color code back to memory
5394
p100Hz1a
5395
 
5396
        ; Check the timeout list to see if there are items ready to be removed from
5397
        ; the list. Also decrement the timeout of the item at the head of the list.
5398
 
5399
p100Hz15:
5400
        ldx             TimeoutList
5401
        bmi             p100Hz12                                ; are there any entries in the timeout list ?
5402
        lda             TCB_Timeout,x
5403
        bne             p100Hz14                                ; has this entry timed out ?
5404
        txa
5405
        jsr             RemoveFromTimeoutList
5406
        jsr             AddTaskToReadyList
5407
        bra             p100Hz15                                ; go back and see if there's another task to be removed
5408
 
5409
p100Hz14:
5410 31 robfinch
        dea                                                             ; decrement the entry's timeout
5411 26 robfinch
        sta             TCB_Timeout,x
5412
 
5413
p100Hz12:
5414
SelectTaskToRun:
5415
        ; Search the ready queues for a ready task.
5416
        ; The search is occasionally started at a lower priority queue in order
5417
        ; to prevent starvation of lower priority tasks. This is managed by
5418
        ; using a tick count as an index to a string containing the start que.
5419
 
5420
        ld              r6,#5                   ; number of queues to search
5421
        ldy             IRQFlag                 ; use the IRQFlag as a buffer index
5422
        lsr             r3,r3,#1                ; the LSB is always the same
5423
        and             r3,r3,#$0F              ; counts from 0 to 15
5424
        lb              r3,strStartQue,y        ; get the queue to start search at
5425
p100Hz2:
5426
        lda             HeadRdy0,y
5427
        bmi             p100Hz1
5428
        ; Move the head of the ready queue to the tail
5429
        jsr             RemoveTaskFromReadyList ; remove task
5430
        jsr             AddTaskToReadyList              ; add it back (automatically goes to tail spot)
5431
        ldx             TCB_Status,r1           ; the task is no longer running
5432
        and             r2,r2,#~TS_RUNNING
5433
        stx             TCB_Status,r1
5434
        lda             HeadRdy0,y
5435
        sta             RunningTCB
5436
        ldx             TCB_Status,r1           ; flag the task as the running task
5437 28 robfinch
        or              r2,r2,#TS_RUNNING       ; task is now running and not preempt
5438
        and             r2,r2,#~TS_PREEMPT
5439 26 robfinch
        stx             TCB_Status,r1
5440
        bra             p100Hz3
5441
p100Hz1:
5442
        iny
5443
        cpy             #5
5444
        bne             p100Hz5
5445
        ldy             #0
5446
p100Hz5
5447
        dec             r6
5448
        bne             p100Hz2
5449
 
5450
        ; here there were no tasks ready
5451 31 robfinch
        ; this might happen if the interrupt is called before tasks
5452
        ; are setup. Otherwise the IDLE task should at least be running.
5453
        bra             p100Hz6
5454 26 robfinch
p100Hz3:
5455
p100Hz10
5456
        ldx             RunningTCB
5457 31 robfinch
        lda             TCB_ABS8Save,x          ; 8 bit emulation base register
5458
        trs             r1,abs8
5459 26 robfinch
        lda             TCB_SP8Save,x           ; get back eight bit stack pointer
5460
        trs             r1,sp8
5461
        ldx             TCB_SPSave,x            ; get back stack pointer
5462
        txs
5463
        ; restore registers
5464 31 robfinch
p100Hz6:
5465 26 robfinch
        pop             r15
5466
        pop             r14
5467
        pop             r13
5468
        pop             r12
5469
        pop             r11
5470
        pop             r10
5471
        pop             r9
5472
        pop             r8
5473
        pop             r7
5474
        pop             r6
5475
        pop             r5
5476
        pop             r4
5477
        ply
5478
        plx
5479
        pla
5480 15 robfinch
        rti
5481
 
5482 26 robfinch
 
5483 15 robfinch
;------------------------------------------------------------------------------
5484
; 1000 Hz interrupt
5485
; This IRQ must be fast.
5486 26 robfinch
; Increments the millisecond counter
5487 15 robfinch
;------------------------------------------------------------------------------
5488
;
5489
p1000Hz:
5490 31 robfinch
        pha
5491
        lda             #2                                              ; reset edge sense circuit
5492
        sta             PIC_RSTE
5493 15 robfinch
        inc             Milliseconds                    ; increment milliseconds count
5494 31 robfinch
        inc             TEXTSCR+82                              ; update IRQ live indicator on screen
5495
        pla
5496 15 robfinch
        rti
5497
 
5498 31 robfinch
;------------------------------------------------------------------------------
5499
; Sleep interrupt
5500
; This interrupt just selects another task to run. The current task is
5501
; stuck in an infinite loop.
5502
;------------------------------------------------------------------------------
5503 15 robfinch
slp_rout:
5504 31 robfinch
        cld             ; clear extended precision mode
5505
        pha
5506
        phx
5507
        phy
5508
        push    r4
5509
        push    r5
5510
        push    r6
5511
        push    r7
5512
        push    r8
5513
        push    r9
5514
        push    r10
5515
        push    r11
5516
        push    r12
5517
        push    r13
5518
        push    r14
5519
        push    r15
5520
        ldx             RunningTCB
5521
        bmi             RunningTCBErr
5522
        and             r2,r2,#$FF
5523
        tsa                                             ; save off the stack pointer
5524
        sta             TCB_SPSave,x
5525
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
5526
        sta             TCB_SP8Save,x
5527
        lda             TCB_Status,x    ; set the task status to SLEEP
5528
        and             r1,r1,#~TS_RUNNING
5529
        or              r1,r1,#TS_SLEEP
5530
        sta             TCB_Status,x
5531
slp1:
5532
        jmp             SelectTaskToRun
5533
 
5534
;------------------------------------------------------------------------------
5535
; Check for and emulate unsupoorted instructions.
5536
;------------------------------------------------------------------------------
5537
InvalidOpIRQ:
5538
        pha
5539
        phx
5540
        phy
5541
        tsx
5542
        lda             4,x             ; get the address of the invalid op off the stack
5543
        lb              r3,0,r1 ; get the opcode byte
5544
        cpy             #$44    ; is it MVP ?
5545
        beq             EmuMVP
5546
        cpy             #$54    ; is it MVN ?
5547
        beq             EmuMVN
5548
        ; We don't know what the op is. Treat it like a NOP
5549
        ; Increment the address and return.
5550
        pha
5551
        lda             #msgUnimp
5552
        jsr             DisplayStringB
5553
        pla
5554
        jsr             DisplayWord
5555
        jsr             CRLF
5556
        ina
5557
        sta             4,x             ; save incremented return address back to stack
5558
        ldx             #64
5559
ioi1:
5560
        tsr             abs8,r1
5561
        jsr             DisplayWord
5562
        lda             #' '
5563
        jsr             DisplayChar
5564
        dex
5565
        bne             ioi1
5566
        jsr             CRLF
5567
        ply
5568
        plx
5569
        pla
5570 15 robfinch
        rti
5571 31 robfinch
 
5572
EmuMVP:
5573
        push    r4
5574
        push    r5
5575
        tsr             sp,r4
5576
        lda             4,r4
5577
        ldx             3,r4
5578
        ldy             2,r4
5579
EmuMVP1:
5580
        ld              r5,(x)
5581
        st              r5,(y)
5582
        dex
5583
        dey
5584
        dea
5585
        cmp             #$FFFFFFFF
5586
        bne             EmuMVP1
5587
        sta             4,r4
5588
        stx             3,r4
5589
        sty             2,r4
5590
        inc             6,r4            ; increment the return address by one.
5591
        pop             r5
5592
        pop             r4
5593
        ply
5594
        plx
5595
        pla
5596
        rti
5597
 
5598
EmuMVN:
5599
        push    r4
5600
        push    r5
5601
        tsr             sp,r4
5602
        lda             4,r4
5603
        ldx             3,r4
5604
        ldy             2,r4
5605
EmuMVN1:
5606
        ld              r5,(x)
5607
        st              r5,(y)
5608
        inx
5609
        iny
5610
        dea
5611
        cmp             #$FFFFFFFF
5612
        bne             EmuMVN1
5613
        sta             4,r4
5614
        stx             3,r4
5615
        sty             2,r4
5616
        inc             6,r4            ; increment the return address by one.
5617
        pop             r5
5618
        pop             r4
5619
        ply
5620
        plx
5621
        pla
5622
        rti
5623
 
5624
msgUnimp:
5625
        db      "Unimplemented at: ",0
5626
 
5627 15 robfinch
brk_rout:
5628
        rti
5629 31 robfinch
nmirout:
5630
        pha
5631
        phx
5632
        lda             #msgPerr
5633
        jsr             DisplayStringB
5634
        tsx
5635
        lda             4,x
5636
        jsr             DisplayWord
5637
        jsr             CRLF
5638
        plx
5639
        pla
5640 11 robfinch
        rti
5641 31 robfinch
 
5642
msgPerr:
5643
        db      "Parity error at: ",0
5644
 
5645 15 robfinch
message "1298"
5646
include "TinyBasic65002.asm"
5647 18 robfinch
message "1640"
5648 11 robfinch
        org $0FFFFFFF4          ; NMI vector
5649
        dw      nmirout
5650
 
5651
        org     $0FFFFFFF8              ; reset vector, native mode
5652
        dw      start
5653
 
5654
        end
5655
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.