mirror of https://github.com/stid/woz64.git
Fine Tune (progress)
This commit is contained in:
parent
6ff59442ca
commit
a877122710
747
arch/keyb.asm
747
arch/keyb.asm
|
@ -1,747 +0,0 @@
|
||||||
BasicUpstart2(start)
|
|
||||||
|
|
||||||
// c64
|
|
||||||
.const bgcolor = $d020
|
|
||||||
.const bordercolor = $d021
|
|
||||||
.const screenram = $0400
|
|
||||||
|
|
||||||
// kernel functions
|
|
||||||
.const bsout = $ab1e //kernel character output sub
|
|
||||||
.const chrout = $ffd2
|
|
||||||
.const clearscreen = $e544
|
|
||||||
|
|
||||||
// chars
|
|
||||||
.const cr = 13
|
|
||||||
|
|
||||||
// memory map
|
|
||||||
.const kernel = $ff80
|
|
||||||
.const start_basic = $0281
|
|
||||||
.const end_basic = $0037
|
|
||||||
.const step_size_garb = $000f
|
|
||||||
.const dataset = $0090
|
|
||||||
.const input_dev = 153
|
|
||||||
.const out_dev = 154
|
|
||||||
.const time_1 = 160
|
|
||||||
.const time_2 = 161
|
|
||||||
.const time_3 = 162
|
|
||||||
.const ds_motor = 192
|
|
||||||
|
|
||||||
// color petscii
|
|
||||||
.const color_cyan = $9f
|
|
||||||
.const color_light_blue = $9a
|
|
||||||
.const color_green = $1e
|
|
||||||
|
|
||||||
// local const
|
|
||||||
.const pline_len = 40
|
|
||||||
.const hex_open_chr = $5b
|
|
||||||
.const hex_close_chr = $5d
|
|
||||||
|
|
||||||
.macro printHexByte(stringAddr, value) {
|
|
||||||
lda #<stringAddr
|
|
||||||
ldy #>stringAddr
|
|
||||||
ldx value
|
|
||||||
jsr printhex_row
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro printHexWord(stringAddr, value) {
|
|
||||||
bPrint(stringAddr)
|
|
||||||
jsr popenhex
|
|
||||||
lda value+1
|
|
||||||
jsr printhex
|
|
||||||
lda value
|
|
||||||
jsr printhex
|
|
||||||
jsr pclosehex
|
|
||||||
bChar(cr)
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro bPrint(stringAddr) {
|
|
||||||
lda #<stringAddr
|
|
||||||
ldy #>stringAddr
|
|
||||||
jsr bsout
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro bChar(char) {
|
|
||||||
lda #char
|
|
||||||
jsr chrout
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================
|
|
||||||
// code
|
|
||||||
//==========================================================
|
|
||||||
|
|
||||||
start:
|
|
||||||
ldx #$00 // color
|
|
||||||
stx $d021 // set background color
|
|
||||||
stx $d020 // set border color
|
|
||||||
|
|
||||||
jsr clearscreen
|
|
||||||
|
|
||||||
bChar(color_cyan)
|
|
||||||
bPrint(str_about)
|
|
||||||
|
|
||||||
bChar(cr)
|
|
||||||
bChar(color_light_blue)
|
|
||||||
|
|
||||||
getKeyb:
|
|
||||||
jsr Keyboard
|
|
||||||
bcs NoValidInput
|
|
||||||
stx TempX
|
|
||||||
sty TempY
|
|
||||||
cmp #$ff
|
|
||||||
// Check A for Alphanumeric keys
|
|
||||||
beq NoNewAphanumericKey
|
|
||||||
// jsr printhex
|
|
||||||
|
|
||||||
cmp #'m'
|
|
||||||
beq mapMemory
|
|
||||||
cmp #'q'
|
|
||||||
beq exit
|
|
||||||
|
|
||||||
jmp getKeyb
|
|
||||||
|
|
||||||
NoNewAphanumericKey:
|
|
||||||
// Check X & Y for Non-Alphanumeric Keys
|
|
||||||
ldx TempX
|
|
||||||
ldy TempY
|
|
||||||
//stx $0401
|
|
||||||
//sty $0402
|
|
||||||
NoValidInput: // This may be substituted for an errorhandler if needed.
|
|
||||||
jmp getKeyb
|
|
||||||
|
|
||||||
|
|
||||||
exit: rts
|
|
||||||
|
|
||||||
|
|
||||||
mapMemory:
|
|
||||||
ldx #pline_len // lenht of pline
|
|
||||||
jsr pline
|
|
||||||
|
|
||||||
// ----------------------
|
|
||||||
// ------ map table start
|
|
||||||
// ----------------------
|
|
||||||
|
|
||||||
// kernel
|
|
||||||
printHexByte(str_row_kernel, kernel)
|
|
||||||
|
|
||||||
// start basic area
|
|
||||||
printHexWord(str_row_basic_start, start_basic)
|
|
||||||
|
|
||||||
// end basic area
|
|
||||||
printHexWord(str_row_basic_end, end_basic)
|
|
||||||
|
|
||||||
// garbadge
|
|
||||||
printHexByte(str_row_step_size_garb, printhex_row)
|
|
||||||
|
|
||||||
// dataset
|
|
||||||
printHexByte(str_row_dataset, dataset)
|
|
||||||
|
|
||||||
// input dev
|
|
||||||
printHexByte(str_row_input_dev, input_dev)
|
|
||||||
|
|
||||||
// out dev
|
|
||||||
printHexByte(str_row_out_dev, out_dev)
|
|
||||||
|
|
||||||
// time 1
|
|
||||||
printHexByte(str_row_time_1, time_1)
|
|
||||||
|
|
||||||
// time 2
|
|
||||||
printHexByte(str_row_time_2, time_2)
|
|
||||||
|
|
||||||
// time 2
|
|
||||||
printHexByte(str_row_time_2, time_3)
|
|
||||||
|
|
||||||
// dataset motor
|
|
||||||
printHexByte(str_row_ds_motor, ds_motor)
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------
|
|
||||||
// ------ map table end
|
|
||||||
// ----------------------
|
|
||||||
bChar(cr)
|
|
||||||
|
|
||||||
ldx #pline_len
|
|
||||||
jsr pline
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// popenhex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
popenhex:
|
|
||||||
bChar(hex_open_chr)
|
|
||||||
bChar(color_green)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// pclosehex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
pclosehex:
|
|
||||||
bChar(color_light_blue)
|
|
||||||
bChar(hex_close_chr)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// printhex_row
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: msn ascii char
|
|
||||||
// .x: lsn ascii char
|
|
||||||
// .y: value
|
|
||||||
//
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
printhex_row:
|
|
||||||
sta a_cache // preserve a
|
|
||||||
txa // store x using a as it will be lost after bsout
|
|
||||||
pha
|
|
||||||
lda a_cache // get back a
|
|
||||||
jsr bsout
|
|
||||||
jsr popenhex
|
|
||||||
pla // saved x back in a from saved a
|
|
||||||
jsr printhex
|
|
||||||
jsr pclosehex
|
|
||||||
bChar(cr)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// printhex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: byte to convert
|
|
||||||
//
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
printhex:
|
|
||||||
pha
|
|
||||||
jsr binhex
|
|
||||||
jsr chrout
|
|
||||||
txa
|
|
||||||
jsr chrout
|
|
||||||
pla
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// btohex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: byte to convert
|
|
||||||
//
|
|
||||||
// returned values: .a: msn ascii char
|
|
||||||
// .x: lsn ascii char
|
|
||||||
// .y: entry value
|
|
||||||
// ————————————————————————————————————
|
|
||||||
binhex: pha //save byte
|
|
||||||
and #%00001111 //extract lsn
|
|
||||||
tax //save it
|
|
||||||
pla //recover byte
|
|
||||||
lsr //extract...
|
|
||||||
lsr //msn
|
|
||||||
lsr
|
|
||||||
lsr
|
|
||||||
pha //save msn
|
|
||||||
txa //lsn
|
|
||||||
jsr binhex1 //generate ascii lsn
|
|
||||||
tax //save
|
|
||||||
pla //get msn & fall thru
|
|
||||||
//
|
|
||||||
// convert nybble to hex ascii equivalent...
|
|
||||||
binhex1: cmp #$0a
|
|
||||||
bcc binhex2 //in decimal range
|
|
||||||
adc #$66 //hex compensate
|
|
||||||
binhex2: eor #%00110000 //finalize nybble
|
|
||||||
rts //done
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// pline
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .x: lenght
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
pline:
|
|
||||||
cpx #0
|
|
||||||
bne pline_start
|
|
||||||
ldx #12 // default to 12 if 0 is passed in x
|
|
||||||
pline_start: lda #102
|
|
||||||
pline_loop: jsr chrout
|
|
||||||
dex
|
|
||||||
cpx #0
|
|
||||||
bne pline_loop
|
|
||||||
lda #cr
|
|
||||||
jsr chrout
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
.encoding "petscii_mixed"
|
|
||||||
str_about:
|
|
||||||
.text "c=64 mapper v2.0 by =stid="
|
|
||||||
.byte 13, 0
|
|
||||||
str_row_kernel:
|
|
||||||
.text " kernel "
|
|
||||||
.byte 0
|
|
||||||
str_row_basic_start:
|
|
||||||
.text " start basic area "
|
|
||||||
.byte 0
|
|
||||||
str_row_basic_end:
|
|
||||||
.text " end basic area "
|
|
||||||
.byte 0
|
|
||||||
str_row_step_size_garb:
|
|
||||||
.text " step size garbage "
|
|
||||||
.byte 0
|
|
||||||
str_row_dataset:
|
|
||||||
.text " dataset "
|
|
||||||
.byte 0
|
|
||||||
str_row_input_dev:
|
|
||||||
.text " input device "
|
|
||||||
.byte 0
|
|
||||||
str_row_out_dev:
|
|
||||||
.text " output device "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_1:
|
|
||||||
.text " time 1 "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_2:
|
|
||||||
.text " time 2 "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_3:
|
|
||||||
.text " time 3 "
|
|
||||||
.byte 0
|
|
||||||
str_row_ds_motor:
|
|
||||||
.text " dataset motor "
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
a_cache:
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
TempX:
|
|
||||||
.byte 0
|
|
||||||
TempY:
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Keyboard IO Routine
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
By: TWW/CTR
|
|
||||||
|
|
||||||
|
|
||||||
Preparatory Settings
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
None
|
|
||||||
|
|
||||||
|
|
||||||
Destroys
|
|
||||||
~~~~~~~~
|
|
||||||
Accumulator
|
|
||||||
X-Register
|
|
||||||
Y-Register
|
|
||||||
Carry / Zero / Negative
|
|
||||||
$dc00
|
|
||||||
$dc01
|
|
||||||
$50-$5f
|
|
||||||
|
|
||||||
|
|
||||||
Footprint
|
|
||||||
~~~~~~~~~
|
|
||||||
#$206 Bytes
|
|
||||||
|
|
||||||
|
|
||||||
Information
|
|
||||||
~~~~~~~~~~~
|
|
||||||
The routine uses "2 Key rollower" or up to 3 if the key-combination doesen't induce shadowing.
|
|
||||||
If 2 or 3 keys are pressed simultaneously (within 1 scan) a "No Activity" state has to occur before new valid keys are returned.
|
|
||||||
RESTORE is not detectable and must be handled by NMI IRQ.
|
|
||||||
SHIFT LOCK is not detected due to unreliability.
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
~~~~~
|
|
||||||
Example Code:
|
|
||||||
|
|
||||||
jsr Keyboard
|
|
||||||
bcs NoValidInput
|
|
||||||
stx TempX
|
|
||||||
sty TempY
|
|
||||||
cmp #$ff
|
|
||||||
beq NoNewAphanumericKey
|
|
||||||
// Check A for Alphanumeric keys
|
|
||||||
sta $0400
|
|
||||||
NoNewAphanumericKey:
|
|
||||||
// Check X & Y for Non-Alphanumeric Keys
|
|
||||||
ldx TempX
|
|
||||||
ldy TempY
|
|
||||||
stx $0401
|
|
||||||
sty $0402
|
|
||||||
NoValidInput: // This may be substituted for an errorhandler if needed.
|
|
||||||
|
|
||||||
|
|
||||||
Returned
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
+=================================================+
|
|
||||||
| Returned in Accumulator |
|
|
||||||
+===========+===========+=============+===========+
|
|
||||||
| $00 - @ | $10 - p | $20 - SPC | $30 - 0 |
|
|
||||||
| $01 - a | $11 - q | $21 - | $31 - 1 |
|
|
||||||
| $02 - b | $12 - r | $22 - | $32 - 2 |
|
|
||||||
| $03 - c | $13 - s | $23 - | $33 - 3 |
|
|
||||||
| $04 - d | $14 - t | $24 - | $34 - 4 |
|
|
||||||
| $05 - e | $15 - u | $25 - | $35 - 5 |
|
|
||||||
| $06 - f | $16 - v | $26 - | $36 - 6 |
|
|
||||||
| $07 - g | $17 - w | $27 - | $37 - 7 |
|
|
||||||
| $08 - h | $18 - x | $28 - | $38 - 8 |
|
|
||||||
| $09 - i | $19 - y | $29 - | $39 - 9 |
|
|
||||||
| $0a - j | $1a - z | $2a - * | $3a - : |
|
|
||||||
| $0b - k | $1b - | $2b - + | $3b - ; |
|
|
||||||
| $0c - l | $1c - £ | $2c - , | $3c - |
|
|
||||||
| $0d - m | $1d - | $2d - - | $3d - = |
|
|
||||||
| $0e - n | $1e - ^ | $2e - . | $3e - |
|
|
||||||
| $0f - o | $1f - <- | $2f - / | $3f - |
|
|
||||||
+-----------+-----------+-------------+-----------+
|
|
||||||
|
|
||||||
+================================================================================
|
|
||||||
| Return in X-Register |
|
|
||||||
+=========+=========+=========+=========+=========+=========+=========+=========+
|
|
||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
| CRSR UD | F5 | F3 | F1 | F7 | CRSR RL | RETURN |INST/DEL |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|
|
||||||
+================================================================================
|
|
||||||
| Return in Y-Register |
|
|
||||||
+=========+=========+=========+=========+=========+=========+=========+=========+
|
|
||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|RUN STOP | L-SHIFT | C= | R-SHIFT |CLR/HOME | CTRL | | |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|
|
||||||
CARRY:
|
|
||||||
- Set = Error Condition (Check A for code):
|
|
||||||
A = #$01 => No keyboard activity is detected.
|
|
||||||
A = #$02 => Control Port #1 Activity is detected.
|
|
||||||
A = #$03 => Key Shadowing / Ghosting is detected.
|
|
||||||
A = #$04 => 2 or 3 new keys is detected within one scan
|
|
||||||
A = #$05 => Awaiting "No Activity" state
|
|
||||||
- Clear = Valid input
|
|
||||||
A = #$ff => No new Alphanumeric Keys detected (some key(s) being held down AND/OR some Non-Alphanumeric key is causing valid return).
|
|
||||||
A <> #$ff => New Alphanumeric Key returned. Non-Alphanumeric keys may also be returned in X or Y Register
|
|
||||||
|
|
||||||
Issues/ToDo:
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
- None
|
|
||||||
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
- Replace the subroutine with a pseudocommand and account for speedcode parameter (Memory vs. Cycles).
|
|
||||||
- Shorten the routine / Optimize if possible.
|
|
||||||
|
|
||||||
|
|
||||||
History:
|
|
||||||
~~~~~~~~
|
|
||||||
V2.5 - New test tool.
|
|
||||||
Added return of error codes.
|
|
||||||
Fixed a bug causing Buffer Overflow.
|
|
||||||
Fixed a bug in Non Alphanumerical Flags from 2.0.
|
|
||||||
V2.1 - Shortened the source by adding .for loops & Updated the header and some comments.
|
|
||||||
Added "simultaneous keypress" check.
|
|
||||||
V2.0 - Added return of non-Alphanumeric keys into X & Y-Registers.
|
|
||||||
Small optimizations here and there.
|
|
||||||
V1.1 - Unrolled code to make it faster and optimized other parts of it.
|
|
||||||
Removed SHIFT LOCK scanning.
|
|
||||||
V1.0 - First Working Version along with test tool.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
||||||
|
|
||||||
* = * "Keyboard Scan Routine"
|
|
||||||
|
|
||||||
|
|
||||||
// ZERO PAGE Varibles
|
|
||||||
.const ScanResult = $50 // 8 bytes
|
|
||||||
.const BufferNew = $58 // 3 bytes
|
|
||||||
.const KeyQuantity = $5b // 1 byte
|
|
||||||
.const NonAlphaFlagX = $5c // 1 byte
|
|
||||||
.const NonAlphaFlagY = $5d // 1 byte
|
|
||||||
.const TempZP = $5e // 1 byte
|
|
||||||
.const SimultaneousKeys = $5f // 1 byte
|
|
||||||
|
|
||||||
// Operational Variables
|
|
||||||
.var MaxKeyRollover = 3
|
|
||||||
|
|
||||||
Keyboard:
|
|
||||||
{
|
|
||||||
jmp Main
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for Scanning a Matrix Row
|
|
||||||
|
|
||||||
KeyInRow:
|
|
||||||
asl
|
|
||||||
bcs *+5
|
|
||||||
jsr KeyFound
|
|
||||||
.for (var i = 0 ; i < 7 ; i++) {
|
|
||||||
inx
|
|
||||||
asl
|
|
||||||
bcs *+5
|
|
||||||
jsr KeyFound
|
|
||||||
}
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for handling: Key Found
|
|
||||||
|
|
||||||
KeyFound:
|
|
||||||
stx TempZP
|
|
||||||
dec KeyQuantity
|
|
||||||
bmi OverFlow
|
|
||||||
ldy KeyTable,x
|
|
||||||
ldx KeyQuantity
|
|
||||||
sty BufferNew,x
|
|
||||||
ldx TempZP
|
|
||||||
rts
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for handling: Overflow
|
|
||||||
|
|
||||||
OverFlow:
|
|
||||||
pla // Dirty hack to handle 2 layers of JSR
|
|
||||||
pla
|
|
||||||
pla
|
|
||||||
pla
|
|
||||||
// Don't manipulate last legal buffer as the routine will fix itself once it gets valid input again.
|
|
||||||
lda #$03
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Exit Routine for: No Activity
|
|
||||||
|
|
||||||
NoActivityDetected:
|
|
||||||
// Exit With A = #$01, Carry Set & Reset BufferOld.
|
|
||||||
lda #$00
|
|
||||||
sta SimultaneousAlphanumericKeysFlag // Clear the too many keys flag once a "no activity" state is detected.
|
|
||||||
stx BufferOld
|
|
||||||
stx BufferOld+1
|
|
||||||
stx BufferOld+2
|
|
||||||
sec
|
|
||||||
lda #$01
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Exit Routine for Control Port Activity
|
|
||||||
|
|
||||||
ControlPort:
|
|
||||||
// Exit with A = #$02, Carry Set. Keep BufferOld to verify input after Control Port activity ceases
|
|
||||||
sec
|
|
||||||
lda #$02
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Configure Data Direction Registers
|
|
||||||
Main:
|
|
||||||
ldx #$ff
|
|
||||||
stx $dc02 // Port A - Output
|
|
||||||
ldy #$00
|
|
||||||
sty $dc03 // Port B - Input
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Port Activity
|
|
||||||
|
|
||||||
sty $dc00 // Connect all Keyboard Rows
|
|
||||||
cpx $dc01
|
|
||||||
beq NoActivityDetected
|
|
||||||
|
|
||||||
lda SimultaneousAlphanumericKeysFlag
|
|
||||||
beq !+
|
|
||||||
// Waiting for all keys to be released before accepting new input.
|
|
||||||
lda #$05
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
!:
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Control Port #1 Activity
|
|
||||||
|
|
||||||
stx $dc00 // Disconnect all Keyboard Rows
|
|
||||||
cpx $dc01 // Only Control Port activity will be detected
|
|
||||||
bne ControlPort
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Scan Keyboard Matrix
|
|
||||||
|
|
||||||
lda #%11111110
|
|
||||||
sta $dc00
|
|
||||||
ldy $dc01
|
|
||||||
sty ScanResult+7
|
|
||||||
sec
|
|
||||||
.for (var i = 6 ; i > -1 ; i--) {
|
|
||||||
rol
|
|
||||||
sta $dc00
|
|
||||||
ldy $dc01
|
|
||||||
sty ScanResult+i
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Control Port #1 Activity (again)
|
|
||||||
|
|
||||||
stx $dc00 // Disconnect all Keyboard Rows
|
|
||||||
cpx $dc01 // Only Control Port activity will be detected
|
|
||||||
bne ControlPort
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Initialize Buffer, Flags and Max Keys
|
|
||||||
|
|
||||||
// Reset current read buffer
|
|
||||||
stx BufferNew
|
|
||||||
stx BufferNew+1
|
|
||||||
stx BufferNew+2
|
|
||||||
|
|
||||||
// Reset Non-AlphaNumeric Flag
|
|
||||||
inx
|
|
||||||
stx NonAlphaFlagY
|
|
||||||
|
|
||||||
// Set max keys allowed before ignoring result
|
|
||||||
lda #MaxKeyRollover
|
|
||||||
sta KeyQuantity
|
|
||||||
|
|
||||||
// Counter to check for simultaneous alphanumeric key-presses
|
|
||||||
lda #$fe
|
|
||||||
sta SimultaneousKeys
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check and flag Non Alphanumeric Keys
|
|
||||||
|
|
||||||
lda ScanResult+6
|
|
||||||
eor #$ff
|
|
||||||
and #%10000000 // Left Shift
|
|
||||||
lsr
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
lda ScanResult+0
|
|
||||||
eor #$ff
|
|
||||||
and #%10100100 // RUN STOP - C= - CTRL
|
|
||||||
ora NonAlphaFlagY
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
lda ScanResult+1
|
|
||||||
eor #$ff
|
|
||||||
and #%00011000 // Right SHIFT - CLR HOME
|
|
||||||
ora NonAlphaFlagY
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
|
|
||||||
lda ScanResult+7 // The rest
|
|
||||||
eor #$ff
|
|
||||||
sta NonAlphaFlagX
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for pressed key(s)
|
|
||||||
|
|
||||||
lda ScanResult+7
|
|
||||||
cmp #$ff
|
|
||||||
beq *+5
|
|
||||||
jsr KeyInRow
|
|
||||||
.for (var i = 6 ; i > -1 ; i--) {
|
|
||||||
ldx #[7-i]*8
|
|
||||||
lda ScanResult+i
|
|
||||||
beq *+5
|
|
||||||
jsr KeyInRow
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Key Scan Completed
|
|
||||||
|
|
||||||
// Put any new key (not in old scan) into buffer
|
|
||||||
ldx #MaxKeyRollover-1
|
|
||||||
!: lda BufferNew,x
|
|
||||||
cmp #$ff
|
|
||||||
beq Exist // Handle 'null' values
|
|
||||||
cmp BufferOld
|
|
||||||
beq Exist
|
|
||||||
cmp BufferOld+1
|
|
||||||
beq Exist
|
|
||||||
cmp BufferOld+2
|
|
||||||
beq Exist
|
|
||||||
// New Key Detected
|
|
||||||
inc BufferQuantity
|
|
||||||
ldy BufferQuantity
|
|
||||||
sta Buffer,y
|
|
||||||
// Keep track of how many new Alphanumeric keys are detected
|
|
||||||
inc SimultaneousKeys
|
|
||||||
beq TooManyNewKeys
|
|
||||||
Exist:
|
|
||||||
dex
|
|
||||||
bpl !-
|
|
||||||
|
|
||||||
// Anything in Buffer?
|
|
||||||
ldy BufferQuantity
|
|
||||||
bmi BufferEmpty
|
|
||||||
// Yes: Then return it and tidy up the buffer
|
|
||||||
dec BufferQuantity
|
|
||||||
lda Buffer
|
|
||||||
ldx Buffer+1
|
|
||||||
stx Buffer
|
|
||||||
ldx Buffer+2
|
|
||||||
stx Buffer+1
|
|
||||||
jmp Return
|
|
||||||
|
|
||||||
BufferEmpty: // No new Alphanumeric keys to handle.
|
|
||||||
lda #$ff
|
|
||||||
|
|
||||||
Return: // A is preset
|
|
||||||
clc
|
|
||||||
// Copy BufferNew to BufferOld
|
|
||||||
ldx BufferNew
|
|
||||||
stx BufferOld
|
|
||||||
ldx BufferNew+1
|
|
||||||
stx BufferOld+1
|
|
||||||
ldx BufferNew+2
|
|
||||||
stx BufferOld+2
|
|
||||||
// Handle Non Alphanumeric Keys
|
|
||||||
ldx NonAlphaFlagX
|
|
||||||
ldy NonAlphaFlagY
|
|
||||||
rts
|
|
||||||
|
|
||||||
TooManyNewKeys:
|
|
||||||
sec
|
|
||||||
lda #$ff
|
|
||||||
sta BufferQuantity
|
|
||||||
sta SimultaneousAlphanumericKeysFlag
|
|
||||||
lda #$04
|
|
||||||
rts
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
KeyTable:
|
|
||||||
.byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff // CRSR DOWN, F5, F3, F1, F7, CRSR RIGHT, RETURN, INST DEL
|
|
||||||
.byte $ff, $05, $13, $1a, $34, $01, $17, $33 // LEFT SHIFT, "E", "S", "Z", "4", "A", "W", "3"
|
|
||||||
.byte $18, $14, $06, $03, $36, $04, $12, $35 // "X", "T", "F", "C", "6", "D", "R", "5"
|
|
||||||
.byte $16, $15, $08, $02, $38, $07, $19, $37 // "V", "U", "H", "B", "8", "G", "Y", "7"
|
|
||||||
.byte $0e, $0f, $0b, $0d, $30, $0a, $09, $39 // "N", "O" (Oscar), "K", "M", "0" (Zero), "J", "I", "9"
|
|
||||||
.byte $2c, $00, $3a, $2e, $2d, $0c, $10, $2b // ",", "@", ":", ".", "-", "L", "P", "+"
|
|
||||||
.byte $2f, $1e, $3d, $ff, $ff, $3b, $2a, $1c // "/", "^", "=", RIGHT SHIFT, HOME, ";", "*", "£"
|
|
||||||
.byte $ff, $11, $ff, $20, $32, $ff, $1f, $31 // RUN STOP, "Q", "C=" (CMD), " " (SPC), "2", "CTRL", "<-", "1"
|
|
||||||
|
|
||||||
BufferOld:
|
|
||||||
.byte $ff, $ff, $ff
|
|
||||||
|
|
||||||
Buffer:
|
|
||||||
.byte $ff, $ff, $ff, $ff
|
|
||||||
|
|
||||||
BufferQuantity:
|
|
||||||
.byte $ff
|
|
||||||
|
|
||||||
SimultaneousAlphanumericKeysFlag:
|
|
||||||
.byte $00
|
|
||||||
}
|
|
|
@ -1,801 +0,0 @@
|
||||||
BasicUpstart2(start)
|
|
||||||
|
|
||||||
// c64
|
|
||||||
.const bgcolor = $d020
|
|
||||||
.const bordercolor = $d021
|
|
||||||
.const screenram = $0400
|
|
||||||
|
|
||||||
// kernel functions
|
|
||||||
.const kBsout = $ab1e //kernel character output sub
|
|
||||||
.const kChrout = $ffd2
|
|
||||||
.const clearscreen = $e544
|
|
||||||
|
|
||||||
// chars
|
|
||||||
.const cr = 13
|
|
||||||
|
|
||||||
// memory map
|
|
||||||
.const kernel = $ff80
|
|
||||||
.const start_basic = $0281
|
|
||||||
.const end_basic = $0037
|
|
||||||
.const step_size_garb = $000f
|
|
||||||
.const dataset = $0090
|
|
||||||
.const input_dev = 153
|
|
||||||
.const out_dev = 154
|
|
||||||
.const time_1 = 160
|
|
||||||
.const time_2 = 161
|
|
||||||
.const time_3 = 162
|
|
||||||
.const ds_motor = 192
|
|
||||||
|
|
||||||
// color petscii
|
|
||||||
.const color_cyan = $9f
|
|
||||||
.const color_light_blue = $9a
|
|
||||||
.const color_green = $1e
|
|
||||||
|
|
||||||
// local const
|
|
||||||
.const pline_len = 40
|
|
||||||
.const hex_open_chr = $5b
|
|
||||||
.const hex_close_chr = $5d
|
|
||||||
|
|
||||||
// zero page
|
|
||||||
.const stringLow = $FB
|
|
||||||
.const stirngHigh = $FC
|
|
||||||
|
|
||||||
.const videoLow = $FD
|
|
||||||
.const videoHigh = $FE
|
|
||||||
|
|
||||||
|
|
||||||
.macro printHexByte(stringAddr, value) {
|
|
||||||
lda #<stringAddr
|
|
||||||
ldy #>stringAddr
|
|
||||||
ldx value
|
|
||||||
jsr printhex_row
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro printHexWord(stringAddr, value) {
|
|
||||||
bPrint(stringAddr)
|
|
||||||
jsr popenhex
|
|
||||||
lda value+1
|
|
||||||
jsr printhex
|
|
||||||
lda value
|
|
||||||
jsr printhex
|
|
||||||
jsr pclosehex
|
|
||||||
bChar(cr)
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro print(stringAddr) {
|
|
||||||
lda #<stringAddr
|
|
||||||
ldy #>stringAddr
|
|
||||||
jsr bsout
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro bPrint(stringAddr) {
|
|
||||||
lda #<stringAddr
|
|
||||||
ldy #>stringAddr
|
|
||||||
jsr bsout
|
|
||||||
}
|
|
||||||
|
|
||||||
.macro bChar(char) {
|
|
||||||
lda #char
|
|
||||||
jsr kChrout
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================
|
|
||||||
// code
|
|
||||||
//==========================================================
|
|
||||||
|
|
||||||
start:
|
|
||||||
ldx #$00 // color
|
|
||||||
stx $d021 // set background color
|
|
||||||
stx $d020 // set border color
|
|
||||||
|
|
||||||
lda #$04
|
|
||||||
sta videoHigh
|
|
||||||
lda #$00
|
|
||||||
sta videoLow
|
|
||||||
|
|
||||||
jsr clearscreen
|
|
||||||
|
|
||||||
bChar(color_cyan)
|
|
||||||
print(str_about)
|
|
||||||
|
|
||||||
bChar(cr)
|
|
||||||
bChar(color_light_blue)
|
|
||||||
|
|
||||||
getKeyb:
|
|
||||||
jsr Keyboard
|
|
||||||
bcs NoValidInput
|
|
||||||
stx TempX
|
|
||||||
sty TempY
|
|
||||||
cmp #$ff
|
|
||||||
// Check A for Alphanumeric keys
|
|
||||||
beq NoNewAphanumericKey
|
|
||||||
// jsr printhex
|
|
||||||
|
|
||||||
cmp #'m'
|
|
||||||
beq mapMemory
|
|
||||||
cmp #'q'
|
|
||||||
beq exit
|
|
||||||
|
|
||||||
jmp getKeyb
|
|
||||||
|
|
||||||
NoNewAphanumericKey:
|
|
||||||
// Check X & Y for Non-Alphanumeric Keys
|
|
||||||
ldx TempX
|
|
||||||
ldy TempY
|
|
||||||
//stx $0401
|
|
||||||
//sty $0402
|
|
||||||
NoValidInput: // This may be substituted for an errorhandler if needed.
|
|
||||||
jmp getKeyb
|
|
||||||
|
|
||||||
exit: rts
|
|
||||||
|
|
||||||
|
|
||||||
bsout:
|
|
||||||
sty stirngHigh
|
|
||||||
sta stringLow
|
|
||||||
|
|
||||||
|
|
||||||
ldy #$00
|
|
||||||
bloop: lda (stringLow), y
|
|
||||||
cmp #0
|
|
||||||
beq blexit
|
|
||||||
sta (videoLow), y
|
|
||||||
iny
|
|
||||||
cpy #$f0
|
|
||||||
bne bcontinue
|
|
||||||
clc
|
|
||||||
lda videoLow
|
|
||||||
adc #$f0
|
|
||||||
sta videoLow
|
|
||||||
lda videoHigh
|
|
||||||
adc #$00
|
|
||||||
sta videoHigh
|
|
||||||
bcontinue: jmp bloop
|
|
||||||
blexit:
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mapMemory: {
|
|
||||||
ldx #pline_len // lenht of pline
|
|
||||||
jsr pline
|
|
||||||
|
|
||||||
// ----------------------
|
|
||||||
// ------ map table start
|
|
||||||
// ----------------------
|
|
||||||
|
|
||||||
// kernel
|
|
||||||
printHexByte(str_row_kernel, kernel)
|
|
||||||
|
|
||||||
// start basic area
|
|
||||||
printHexWord(str_row_basic_start, start_basic)
|
|
||||||
|
|
||||||
// end basic area
|
|
||||||
printHexWord(str_row_basic_end, end_basic)
|
|
||||||
|
|
||||||
// garbadge
|
|
||||||
printHexByte(str_row_step_size_garb, printhex_row)
|
|
||||||
|
|
||||||
// dataset
|
|
||||||
printHexByte(str_row_dataset, dataset)
|
|
||||||
|
|
||||||
// input dev
|
|
||||||
printHexByte(str_row_input_dev, input_dev)
|
|
||||||
|
|
||||||
// out dev
|
|
||||||
printHexByte(str_row_out_dev, out_dev)
|
|
||||||
|
|
||||||
// time 1
|
|
||||||
printHexByte(str_row_time_1, time_1)
|
|
||||||
|
|
||||||
// time 2
|
|
||||||
printHexByte(str_row_time_2, time_2)
|
|
||||||
|
|
||||||
// time 2
|
|
||||||
printHexByte(str_row_time_2, time_3)
|
|
||||||
|
|
||||||
// dataset motor
|
|
||||||
printHexByte(str_row_ds_motor, ds_motor)
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------
|
|
||||||
// ------ map table end
|
|
||||||
// ----------------------
|
|
||||||
bChar(cr)
|
|
||||||
|
|
||||||
ldx #pline_len
|
|
||||||
jsr pline
|
|
||||||
rts
|
|
||||||
}
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// popenhex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
popenhex:
|
|
||||||
bChar(hex_open_chr)
|
|
||||||
bChar(color_green)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// pclosehex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
pclosehex:
|
|
||||||
bChar(color_light_blue)
|
|
||||||
bChar(hex_close_chr)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// printhex_row
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: msn ascii char
|
|
||||||
// .x: lsn ascii char
|
|
||||||
// .y: value
|
|
||||||
//
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
printhex_row:
|
|
||||||
sta a_cache // preserve a
|
|
||||||
txa // store x using a as it will be lost after ksout
|
|
||||||
pha
|
|
||||||
lda a_cache // get back a
|
|
||||||
jsr bsout
|
|
||||||
jsr popenhex
|
|
||||||
pla // saved x back in a from saved a
|
|
||||||
jsr printhex
|
|
||||||
jsr pclosehex
|
|
||||||
bChar(cr)
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// printhex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: byte to convert
|
|
||||||
//
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
printhex:
|
|
||||||
pha
|
|
||||||
jsr binhex
|
|
||||||
jsr kChrout
|
|
||||||
txa
|
|
||||||
jsr kChrout
|
|
||||||
pla
|
|
||||||
rts
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// btohex
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .a: byte to convert
|
|
||||||
//
|
|
||||||
// returned values: .a: msn ascii char
|
|
||||||
// .x: lsn ascii char
|
|
||||||
// .y: entry value
|
|
||||||
// ————————————————————————————————————
|
|
||||||
binhex: pha //save byte
|
|
||||||
and #%00001111 //extract lsn
|
|
||||||
tax //save it
|
|
||||||
pla //recover byte
|
|
||||||
lsr //extract...
|
|
||||||
lsr //msn
|
|
||||||
lsr
|
|
||||||
lsr
|
|
||||||
pha //save msn
|
|
||||||
txa //lsn
|
|
||||||
jsr binhex1 //generate ascii lsn
|
|
||||||
tax //save
|
|
||||||
pla //get msn & fall thru
|
|
||||||
//
|
|
||||||
// convert nybble to hex ascii equivalent...
|
|
||||||
binhex1: cmp #$0a
|
|
||||||
bcc binhex2 //in decimal range
|
|
||||||
adc #$66 //hex compensate
|
|
||||||
binhex2: eor #%00110000 //finalize nybble
|
|
||||||
rts //done
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// pline
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// ————————————————————————————————————
|
|
||||||
// preparatory ops: .x: lenght
|
|
||||||
// returned values: none
|
|
||||||
// ————————————————————————————————————
|
|
||||||
pline:
|
|
||||||
cpx #0
|
|
||||||
bne pline_start
|
|
||||||
ldx #12 // default to 12 if 0 is passed in x
|
|
||||||
pline_start: lda #102
|
|
||||||
pline_loop: jsr kChrout
|
|
||||||
dex
|
|
||||||
cpx #0
|
|
||||||
bne pline_loop
|
|
||||||
lda #cr
|
|
||||||
jsr kChrout
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
.encoding "screencode_mixed"
|
|
||||||
str_about:
|
|
||||||
.text "c=64 mapper v2.0 by =stid="
|
|
||||||
.byte 0
|
|
||||||
str_row_kernel:
|
|
||||||
.text " kernel "
|
|
||||||
.byte 0
|
|
||||||
str_row_basic_start:
|
|
||||||
.text " start basic area "
|
|
||||||
.byte 0
|
|
||||||
str_row_basic_end:
|
|
||||||
.text " end basic area "
|
|
||||||
.byte 0
|
|
||||||
str_row_step_size_garb:
|
|
||||||
.text " step size garbage "
|
|
||||||
.byte 0
|
|
||||||
str_row_dataset:
|
|
||||||
.text " dataset "
|
|
||||||
.byte 0
|
|
||||||
str_row_input_dev:
|
|
||||||
.text " input device "
|
|
||||||
.byte 0
|
|
||||||
str_row_out_dev:
|
|
||||||
.text " output device "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_1:
|
|
||||||
.text " time 1 "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_2:
|
|
||||||
.text " time 2 "
|
|
||||||
.byte 0
|
|
||||||
str_row_time_3:
|
|
||||||
.text " time 3 "
|
|
||||||
.byte 0
|
|
||||||
str_row_ds_motor:
|
|
||||||
.text " dataset motor "
|
|
||||||
.byte 0
|
|
||||||
str_row_generic:
|
|
||||||
.text " hex value "
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
|
|
||||||
a_cache:
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
TempX:
|
|
||||||
.byte 0
|
|
||||||
TempY:
|
|
||||||
.byte 0
|
|
||||||
cursorX:
|
|
||||||
.byte 0
|
|
||||||
cursorY:
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Keyboard IO Routine
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
By: TWW/CTR
|
|
||||||
|
|
||||||
|
|
||||||
Preparatory Settings
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
None
|
|
||||||
|
|
||||||
|
|
||||||
Destroys
|
|
||||||
~~~~~~~~
|
|
||||||
Accumulator
|
|
||||||
X-Register
|
|
||||||
Y-Register
|
|
||||||
Carry / Zero / Negative
|
|
||||||
$dc00
|
|
||||||
$dc01
|
|
||||||
$50-$5f
|
|
||||||
|
|
||||||
|
|
||||||
Footprint
|
|
||||||
~~~~~~~~~
|
|
||||||
#$206 Bytes
|
|
||||||
|
|
||||||
|
|
||||||
Information
|
|
||||||
~~~~~~~~~~~
|
|
||||||
The routine uses "2 Key rollower" or up to 3 if the key-combination doesen't induce shadowing.
|
|
||||||
If 2 or 3 keys are pressed simultaneously (within 1 scan) a "No Activity" state has to occur before new valid keys are returned.
|
|
||||||
RESTORE is not detectable and must be handled by NMI IRQ.
|
|
||||||
SHIFT LOCK is not detected due to unreliability.
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
~~~~~
|
|
||||||
Example Code:
|
|
||||||
|
|
||||||
jsr Keyboard
|
|
||||||
bcs NoValidInput
|
|
||||||
stx TempX
|
|
||||||
sty TempY
|
|
||||||
cmp #$ff
|
|
||||||
beq NoNewAphanumericKey
|
|
||||||
// Check A for Alphanumeric keys
|
|
||||||
sta $0400
|
|
||||||
NoNewAphanumericKey:
|
|
||||||
// Check X & Y for Non-Alphanumeric Keys
|
|
||||||
ldx TempX
|
|
||||||
ldy TempY
|
|
||||||
stx $0401
|
|
||||||
sty $0402
|
|
||||||
NoValidInput: // This may be substituted for an errorhandler if needed.
|
|
||||||
|
|
||||||
|
|
||||||
Returned
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
+=================================================+
|
|
||||||
| Returned in Accumulator |
|
|
||||||
+===========+===========+=============+===========+
|
|
||||||
| $00 - @ | $10 - p | $20 - SPC | $30 - 0 |
|
|
||||||
| $01 - a | $11 - q | $21 - | $31 - 1 |
|
|
||||||
| $02 - b | $12 - r | $22 - | $32 - 2 |
|
|
||||||
| $03 - c | $13 - s | $23 - | $33 - 3 |
|
|
||||||
| $04 - d | $14 - t | $24 - | $34 - 4 |
|
|
||||||
| $05 - e | $15 - u | $25 - | $35 - 5 |
|
|
||||||
| $06 - f | $16 - v | $26 - | $36 - 6 |
|
|
||||||
| $07 - g | $17 - w | $27 - | $37 - 7 |
|
|
||||||
| $08 - h | $18 - x | $28 - | $38 - 8 |
|
|
||||||
| $09 - i | $19 - y | $29 - | $39 - 9 |
|
|
||||||
| $0a - j | $1a - z | $2a - * | $3a - : |
|
|
||||||
| $0b - k | $1b - | $2b - + | $3b - ; |
|
|
||||||
| $0c - l | $1c - £ | $2c - , | $3c - |
|
|
||||||
| $0d - m | $1d - | $2d - - | $3d - = |
|
|
||||||
| $0e - n | $1e - ^ | $2e - . | $3e - |
|
|
||||||
| $0f - o | $1f - <- | $2f - / | $3f - |
|
|
||||||
+-----------+-----------+-------------+-----------+
|
|
||||||
|
|
||||||
+================================================================================
|
|
||||||
| Return in X-Register |
|
|
||||||
+=========+=========+=========+=========+=========+=========+=========+=========+
|
|
||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
| CRSR UD | F5 | F3 | F1 | F7 | CRSR RL | RETURN |INST/DEL |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|
|
||||||
+================================================================================
|
|
||||||
| Return in Y-Register |
|
|
||||||
+=========+=========+=========+=========+=========+=========+=========+=========+
|
|
||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|RUN STOP | L-SHIFT | C= | R-SHIFT |CLR/HOME | CTRL | | |
|
|
||||||
+---------+---------+---------+---------+---------+---------+---------+---------+
|
|
||||||
|
|
||||||
CARRY:
|
|
||||||
- Set = Error Condition (Check A for code):
|
|
||||||
A = #$01 => No keyboard activity is detected.
|
|
||||||
A = #$02 => Control Port #1 Activity is detected.
|
|
||||||
A = #$03 => Key Shadowing / Ghosting is detected.
|
|
||||||
A = #$04 => 2 or 3 new keys is detected within one scan
|
|
||||||
A = #$05 => Awaiting "No Activity" state
|
|
||||||
- Clear = Valid input
|
|
||||||
A = #$ff => No new Alphanumeric Keys detected (some key(s) being held down AND/OR some Non-Alphanumeric key is causing valid return).
|
|
||||||
A <> #$ff => New Alphanumeric Key returned. Non-Alphanumeric keys may also be returned in X or Y Register
|
|
||||||
|
|
||||||
Issues/ToDo:
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
- None
|
|
||||||
|
|
||||||
|
|
||||||
Improvements:
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
- Replace the subroutine with a pseudocommand and account for speedcode parameter (Memory vs. Cycles).
|
|
||||||
- Shorten the routine / Optimize if possible.
|
|
||||||
|
|
||||||
|
|
||||||
History:
|
|
||||||
~~~~~~~~
|
|
||||||
V2.5 - New test tool.
|
|
||||||
Added return of error codes.
|
|
||||||
Fixed a bug causing Buffer Overflow.
|
|
||||||
Fixed a bug in Non Alphanumerical Flags from 2.0.
|
|
||||||
V2.1 - Shortened the source by adding .for loops & Updated the header and some comments.
|
|
||||||
Added "simultaneous keypress" check.
|
|
||||||
V2.0 - Added return of non-Alphanumeric keys into X & Y-Registers.
|
|
||||||
Small optimizations here and there.
|
|
||||||
V1.1 - Unrolled code to make it faster and optimized other parts of it.
|
|
||||||
Removed SHIFT LOCK scanning.
|
|
||||||
V1.0 - First Working Version along with test tool.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
||||||
|
|
||||||
* = * "Keyboard Scan Routine"
|
|
||||||
|
|
||||||
|
|
||||||
// ZERO PAGE Varibles
|
|
||||||
.const ScanResult = $50 // 8 bytes
|
|
||||||
.const BufferNew = $58 // 3 bytes
|
|
||||||
.const KeyQuantity = $5b // 1 byte
|
|
||||||
.const NonAlphaFlagX = $5c // 1 byte
|
|
||||||
.const NonAlphaFlagY = $5d // 1 byte
|
|
||||||
.const TempZP = $5e // 1 byte
|
|
||||||
.const SimultaneousKeys = $5f // 1 byte
|
|
||||||
|
|
||||||
// Operational Variables
|
|
||||||
.var MaxKeyRollover = 3
|
|
||||||
|
|
||||||
Keyboard:
|
|
||||||
{
|
|
||||||
jmp Main
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for Scanning a Matrix Row
|
|
||||||
|
|
||||||
KeyInRow:
|
|
||||||
asl
|
|
||||||
bcs *+5
|
|
||||||
jsr KeyFound
|
|
||||||
.for (var i = 0 ; i < 7 ; i++) {
|
|
||||||
inx
|
|
||||||
asl
|
|
||||||
bcs *+5
|
|
||||||
jsr KeyFound
|
|
||||||
}
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for handling: Key Found
|
|
||||||
|
|
||||||
KeyFound:
|
|
||||||
stx TempZP
|
|
||||||
dec KeyQuantity
|
|
||||||
bmi OverFlow
|
|
||||||
ldy KeyTable,x
|
|
||||||
ldx KeyQuantity
|
|
||||||
sty BufferNew,x
|
|
||||||
ldx TempZP
|
|
||||||
rts
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Routine for handling: Overflow
|
|
||||||
|
|
||||||
OverFlow:
|
|
||||||
pla // Dirty hack to handle 2 layers of JSR
|
|
||||||
pla
|
|
||||||
pla
|
|
||||||
pla
|
|
||||||
// Don't manipulate last legal buffer as the routine will fix itself once it gets valid input again.
|
|
||||||
lda #$03
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Exit Routine for: No Activity
|
|
||||||
|
|
||||||
NoActivityDetected:
|
|
||||||
// Exit With A = #$01, Carry Set & Reset BufferOld.
|
|
||||||
lda #$00
|
|
||||||
sta SimultaneousAlphanumericKeysFlag // Clear the too many keys flag once a "no activity" state is detected.
|
|
||||||
stx BufferOld
|
|
||||||
stx BufferOld+1
|
|
||||||
stx BufferOld+2
|
|
||||||
sec
|
|
||||||
lda #$01
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Exit Routine for Control Port Activity
|
|
||||||
|
|
||||||
ControlPort:
|
|
||||||
// Exit with A = #$02, Carry Set. Keep BufferOld to verify input after Control Port activity ceases
|
|
||||||
sec
|
|
||||||
lda #$02
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Configure Data Direction Registers
|
|
||||||
Main:
|
|
||||||
ldx #$ff
|
|
||||||
stx $dc02 // Port A - Output
|
|
||||||
ldy #$00
|
|
||||||
sty $dc03 // Port B - Input
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Port Activity
|
|
||||||
|
|
||||||
sty $dc00 // Connect all Keyboard Rows
|
|
||||||
cpx $dc01
|
|
||||||
beq NoActivityDetected
|
|
||||||
|
|
||||||
lda SimultaneousAlphanumericKeysFlag
|
|
||||||
beq !+
|
|
||||||
// Waiting for all keys to be released before accepting new input.
|
|
||||||
lda #$05
|
|
||||||
sec
|
|
||||||
rts
|
|
||||||
!:
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Control Port #1 Activity
|
|
||||||
|
|
||||||
stx $dc00 // Disconnect all Keyboard Rows
|
|
||||||
cpx $dc01 // Only Control Port activity will be detected
|
|
||||||
bne ControlPort
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Scan Keyboard Matrix
|
|
||||||
|
|
||||||
lda #%11111110
|
|
||||||
sta $dc00
|
|
||||||
ldy $dc01
|
|
||||||
sty ScanResult+7
|
|
||||||
sec
|
|
||||||
.for (var i = 6 ; i > -1 ; i--) {
|
|
||||||
rol
|
|
||||||
sta $dc00
|
|
||||||
ldy $dc01
|
|
||||||
sty ScanResult+i
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for Control Port #1 Activity (again)
|
|
||||||
|
|
||||||
stx $dc00 // Disconnect all Keyboard Rows
|
|
||||||
cpx $dc01 // Only Control Port activity will be detected
|
|
||||||
bne ControlPort
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Initialize Buffer, Flags and Max Keys
|
|
||||||
|
|
||||||
// Reset current read buffer
|
|
||||||
stx BufferNew
|
|
||||||
stx BufferNew+1
|
|
||||||
stx BufferNew+2
|
|
||||||
|
|
||||||
// Reset Non-AlphaNumeric Flag
|
|
||||||
inx
|
|
||||||
stx NonAlphaFlagY
|
|
||||||
|
|
||||||
// Set max keys allowed before ignoring result
|
|
||||||
lda #MaxKeyRollover
|
|
||||||
sta KeyQuantity
|
|
||||||
|
|
||||||
// Counter to check for simultaneous alphanumeric key-presses
|
|
||||||
lda #$fe
|
|
||||||
sta SimultaneousKeys
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check and flag Non Alphanumeric Keys
|
|
||||||
|
|
||||||
lda ScanResult+6
|
|
||||||
eor #$ff
|
|
||||||
and #%10000000 // Left Shift
|
|
||||||
lsr
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
lda ScanResult+0
|
|
||||||
eor #$ff
|
|
||||||
and #%10100100 // RUN STOP - C= - CTRL
|
|
||||||
ora NonAlphaFlagY
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
lda ScanResult+1
|
|
||||||
eor #$ff
|
|
||||||
and #%00011000 // Right SHIFT - CLR HOME
|
|
||||||
ora NonAlphaFlagY
|
|
||||||
sta NonAlphaFlagY
|
|
||||||
|
|
||||||
lda ScanResult+7 // The rest
|
|
||||||
eor #$ff
|
|
||||||
sta NonAlphaFlagX
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Check for pressed key(s)
|
|
||||||
|
|
||||||
lda ScanResult+7
|
|
||||||
cmp #$ff
|
|
||||||
beq *+5
|
|
||||||
jsr KeyInRow
|
|
||||||
.for (var i = 6 ; i > -1 ; i--) {
|
|
||||||
ldx #[7-i]*8
|
|
||||||
lda ScanResult+i
|
|
||||||
beq *+5
|
|
||||||
jsr KeyInRow
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Key Scan Completed
|
|
||||||
|
|
||||||
// Put any new key (not in old scan) into buffer
|
|
||||||
ldx #MaxKeyRollover-1
|
|
||||||
!: lda BufferNew,x
|
|
||||||
cmp #$ff
|
|
||||||
beq Exist // Handle 'null' values
|
|
||||||
cmp BufferOld
|
|
||||||
beq Exist
|
|
||||||
cmp BufferOld+1
|
|
||||||
beq Exist
|
|
||||||
cmp BufferOld+2
|
|
||||||
beq Exist
|
|
||||||
// New Key Detected
|
|
||||||
inc BufferQuantity
|
|
||||||
ldy BufferQuantity
|
|
||||||
sta Buffer,y
|
|
||||||
// Keep track of how many new Alphanumeric keys are detected
|
|
||||||
inc SimultaneousKeys
|
|
||||||
beq TooManyNewKeys
|
|
||||||
Exist:
|
|
||||||
dex
|
|
||||||
bpl !-
|
|
||||||
|
|
||||||
// Anything in Buffer?
|
|
||||||
ldy BufferQuantity
|
|
||||||
bmi BufferEmpty
|
|
||||||
// Yes: Then return it and tidy up the buffer
|
|
||||||
dec BufferQuantity
|
|
||||||
lda Buffer
|
|
||||||
ldx Buffer+1
|
|
||||||
stx Buffer
|
|
||||||
ldx Buffer+2
|
|
||||||
stx Buffer+1
|
|
||||||
jmp Return
|
|
||||||
|
|
||||||
BufferEmpty: // No new Alphanumeric keys to handle.
|
|
||||||
lda #$ff
|
|
||||||
|
|
||||||
Return: // A is preset
|
|
||||||
clc
|
|
||||||
// Copy BufferNew to BufferOld
|
|
||||||
ldx BufferNew
|
|
||||||
stx BufferOld
|
|
||||||
ldx BufferNew+1
|
|
||||||
stx BufferOld+1
|
|
||||||
ldx BufferNew+2
|
|
||||||
stx BufferOld+2
|
|
||||||
// Handle Non Alphanumeric Keys
|
|
||||||
ldx NonAlphaFlagX
|
|
||||||
ldy NonAlphaFlagY
|
|
||||||
rts
|
|
||||||
|
|
||||||
TooManyNewKeys:
|
|
||||||
sec
|
|
||||||
lda #$ff
|
|
||||||
sta BufferQuantity
|
|
||||||
sta SimultaneousAlphanumericKeysFlag
|
|
||||||
lda #$04
|
|
||||||
rts
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
KeyTable:
|
|
||||||
.byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff // CRSR DOWN, F5, F3, F1, F7, CRSR RIGHT, RETURN, INST DEL
|
|
||||||
.byte $ff, $05, $13, $1a, $34, $01, $17, $33 // LEFT SHIFT, "E", "S", "Z", "4", "A", "W", "3"
|
|
||||||
.byte $18, $14, $06, $03, $36, $04, $12, $35 // "X", "T", "F", "C", "6", "D", "R", "5"
|
|
||||||
.byte $16, $15, $08, $02, $38, $07, $19, $37 // "V", "U", "H", "B", "8", "G", "Y", "7"
|
|
||||||
.byte $0e, $0f, $0b, $0d, $30, $0a, $09, $39 // "N", "O" (Oscar), "K", "M", "0" (Zero), "J", "I", "9"
|
|
||||||
.byte $2c, $00, $3a, $2e, $2d, $0c, $10, $2b // ",", "@", ":", ".", "-", "L", "P", "+"
|
|
||||||
.byte $2f, $1e, $3d, $ff, $ff, $3b, $2a, $1c // "/", "^", "=", RIGHT SHIFT, HOME, ";", "*", "£"
|
|
||||||
.byte $ff, $11, $ff, $20, $32, $ff, $1f, $31 // RUN STOP, "Q", "C=" (CMD), " " (SPC), "2", "CTRL", "<-", "1"
|
|
||||||
|
|
||||||
BufferOld:
|
|
||||||
.byte $ff, $ff, $ff
|
|
||||||
|
|
||||||
Buffer:
|
|
||||||
.byte $ff, $ff, $ff, $ff
|
|
||||||
|
|
||||||
BufferQuantity:
|
|
||||||
.byte $ff
|
|
||||||
|
|
||||||
SimultaneousAlphanumericKeysFlag:
|
|
||||||
.byte $00
|
|
||||||
}
|
|
67
main.asm
67
main.asm
|
@ -1,4 +1,4 @@
|
||||||
//BasicUpstart2(start)
|
// BasicUpstart2(start)
|
||||||
#import "mem_map.asm"
|
#import "mem_map.asm"
|
||||||
|
|
||||||
* = $8000 "Main"
|
* = $8000 "Main"
|
||||||
|
@ -6,9 +6,18 @@
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
.const MAIN_COLOR = $03
|
.const MAIN_COLOR = $03
|
||||||
.const BORDER_COLOR = $05
|
.const BORDER_COLOR = $05
|
||||||
.const SCREEN_MEM = $0400
|
|
||||||
.const CR = $0d
|
.const CR = $0d
|
||||||
.const BS = $14
|
.const BS = $14
|
||||||
|
.const ADV_CHAR = '@'
|
||||||
|
.const INIT_IRQ = $fda3
|
||||||
|
.const INIT_MEM = $fd50
|
||||||
|
.const INIT_IO = $fd15
|
||||||
|
.const INIT_VID = $ff5b
|
||||||
|
.const SCRN_CTRL = $d016
|
||||||
|
.const RASTER_LINE = $d012
|
||||||
|
.const INTERRUPT_CTRL = $dc0d
|
||||||
|
.const NMSK_INTERRUPT_CTRL = $dd0d
|
||||||
|
.const TIMER_A_CTRL = $DC0E
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
.word coldstart // coldstart vector
|
.word coldstart // coldstart vector
|
||||||
|
@ -30,43 +39,50 @@ coldstart:
|
||||||
sei
|
sei
|
||||||
txs
|
txs
|
||||||
cld
|
cld
|
||||||
stx $d016
|
stx SCRN_CTRL // Set Screen Bits
|
||||||
jsr $fda3 // Prepare IRQ
|
jsr INIT_IRQ // Prepare IRQ
|
||||||
jsr $fd50 // Init memory. Rewrite this routine to speed up boot process.
|
jsr INIT_MEM // Init memory. Rewrite this routine to speed up boot process.
|
||||||
jsr $fd15 // Init I/O
|
jsr INIT_IO // Init I/O
|
||||||
jsr $ff5b // Init video
|
jsr INIT_VID // Init video
|
||||||
cli
|
cli
|
||||||
|
|
||||||
|
* = * "App Start"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
start:
|
start:
|
||||||
//sei
|
|
||||||
|
|
||||||
jsr initApp;
|
jsr initApp;
|
||||||
|
print(lineString)
|
||||||
print(testString)
|
print(testString)
|
||||||
|
print(lineString)
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
lda #$FF
|
lda #$FF
|
||||||
Raster: cmp $D012
|
Raster: cmp RASTER_LINE // Raster done?
|
||||||
bne Raster
|
bne Raster
|
||||||
jsr Keyboard2.ReadKeyb
|
jsr Keyboard2.ReadKeyb
|
||||||
jsr Keyboard2.GetKey
|
jsr Keyboard2.GetKey
|
||||||
bcs loop
|
bcs loop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cmp #CR
|
cmp #CR
|
||||||
beq cr
|
beq execute
|
||||||
|
|
||||||
cmp #BS
|
cmp #BS
|
||||||
beq backspace
|
beq backspace
|
||||||
inputChar:
|
inputChar:
|
||||||
jsr Shell.push
|
jsr Shell.push // Char in Buffer
|
||||||
cPrint()
|
cPrint()
|
||||||
jmp loop
|
jmp loop
|
||||||
backspace:
|
backspace:
|
||||||
jsr Shell.backspace
|
jsr Shell.backspace
|
||||||
cPrint()
|
cPrint()
|
||||||
jmp loop
|
jmp loop
|
||||||
cr:
|
|
||||||
jsr Shell.push
|
execute:
|
||||||
|
jsr Shell.push // CR in Buffer
|
||||||
jsr Screen.screenNewLine
|
jsr Screen.screenNewLine
|
||||||
jsr Shell.wozExec
|
jsr Shell.exec
|
||||||
jsr Screen.screenNewLine
|
jsr Screen.screenNewLine
|
||||||
jsr Shell.clear
|
jsr Shell.clear
|
||||||
jmp loop
|
jmp loop
|
||||||
|
@ -76,21 +92,21 @@ initApp: {
|
||||||
|
|
||||||
sei
|
sei
|
||||||
lda #$7f
|
lda #$7f
|
||||||
sta $dc0d // disable timer interrupts which can be generated by the two CIA chips
|
sta INTERRUPT_CTRL // disable timer interrupts which can be generated by the two CIA chips
|
||||||
sta $dd0d // the kernal uses such an interrupt to flash the cursor and scan the keyboard, so we better
|
sta NMSK_INTERRUPT_CTRL // the kernal uses such an interrupt to flash the cursor and scan the keyboard, so we better
|
||||||
// stop it.
|
// stop it.
|
||||||
|
|
||||||
lda $dc0d // by reading this two registers we negate any pending CIA irqs.
|
lda INTERRUPT_CTRL // by reading this two registers we negate any pending CIA irqs.
|
||||||
lda $dd0d // if we don't do this, a pending CIA irq might occur after we finish setting up our irq.
|
lda NMSK_INTERRUPT_CTRL // if we don't do this, a pending CIA irq might occur after we finish setting up our irq.
|
||||||
// we don't want that to happen.
|
// we don't want that to happen.
|
||||||
|
|
||||||
// Disable 0e TIMER
|
// Disable 0e TIMER
|
||||||
lda #254
|
lda #254
|
||||||
and $dc0e
|
and TIMER_A_CTRL
|
||||||
sta $dc0e
|
sta TIMER_A_CTRL
|
||||||
|
|
||||||
ClearColorRam($00)
|
ClearColorRam($00)
|
||||||
ClearScreen(SCREEN_MEM, ' ')
|
ClearScreen(' ')
|
||||||
SetBorderColor(BORDER_COLOR)
|
SetBorderColor(BORDER_COLOR)
|
||||||
SetBackgroundColor(MAIN_COLOR)
|
SetBackgroundColor(MAIN_COLOR)
|
||||||
jsr Screen.init
|
jsr Screen.init
|
||||||
|
@ -118,7 +134,8 @@ minor: .byte 05
|
||||||
|
|
||||||
testString:
|
testString:
|
||||||
.text "woz64 mon - v 0.1.5"
|
.text "woz64 mon - v 0.1.5"
|
||||||
.byte $8e
|
.byte $8e, 0
|
||||||
|
lineString:
|
||||||
.text "----------------------------------------"
|
.text "----------------------------------------"
|
||||||
.byte $8e, 0
|
.byte $8e, 0
|
||||||
hoaxString:
|
hoaxString:
|
||||||
|
|
26
memory.asm
26
memory.asm
|
@ -3,22 +3,22 @@
|
||||||
* = * "Memory Routines"
|
* = * "Memory Routines"
|
||||||
|
|
||||||
.macro clone(from, to, dest) {
|
.macro clone(from, to, dest) {
|
||||||
lda #<from
|
lda #<from
|
||||||
sta MemMap.MEMORY.from
|
sta MemMap.MEMORY.from
|
||||||
lda #>from
|
lda #>from
|
||||||
sta MemMap.MEMORY.from+1
|
sta MemMap.MEMORY.from+1
|
||||||
|
|
||||||
lda #<dest
|
lda #<dest
|
||||||
sta MemMap.MEMORY.dest
|
sta MemMap.MEMORY.dest
|
||||||
lda #>dest
|
lda #>dest
|
||||||
sta MemMap.MEMORY.dest+1
|
sta MemMap.MEMORY.dest+1
|
||||||
|
|
||||||
lda #<to-from
|
lda #<to-from
|
||||||
sta MemMap.MEMORY.size+1
|
sta MemMap.MEMORY.size+1
|
||||||
lda #>to-from
|
lda #>to-from
|
||||||
sta MemMap.MEMORY.size
|
sta MemMap.MEMORY.size
|
||||||
|
|
||||||
jsr Memory._clone
|
jsr Memory._clone
|
||||||
}
|
}
|
||||||
|
|
||||||
.filenamespace Memory
|
.filenamespace Memory
|
||||||
|
|
127
screen.asm
127
screen.asm
|
@ -2,6 +2,8 @@
|
||||||
#import "math.asm"
|
#import "math.asm"
|
||||||
#import "memory.asm"
|
#import "memory.asm"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// MACROS
|
// MACROS
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
@ -9,83 +11,80 @@
|
||||||
* = * "Screen Routines"
|
* = * "Screen Routines"
|
||||||
|
|
||||||
.macro print(stringAddr) {
|
.macro print(stringAddr) {
|
||||||
lda #<stringAddr // Low byte
|
lda #<stringAddr // Low byte
|
||||||
ldx #>stringAddr // High byte
|
ldx #>stringAddr // High byte
|
||||||
jsr Screen.print
|
jsr Screen.print
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro cPrint() {
|
.macro cPrint() {
|
||||||
jsr Screen.printPetChar
|
jsr Screen.printPetChar
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro ClearScreen(screen, clearByte) {
|
.macro ClearChunks(baseAddress, clearByte) {
|
||||||
lda #clearByte
|
lda #clearByte
|
||||||
ldx #0
|
ldx #0
|
||||||
!loop:
|
!loop:
|
||||||
sta screen, x
|
sta baseAddress, x
|
||||||
sta screen + $100, x
|
sta baseAddress + $100, x
|
||||||
sta screen + $200, x
|
sta baseAddress + $200, x
|
||||||
sta screen + $300, x
|
sta baseAddress + $300, x
|
||||||
inx
|
inx
|
||||||
bne.r !loop-
|
bne.r !loop-
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.macro ClearScreen(clearByte) {
|
||||||
|
ClearChunks(Screen.VIDEO_ADDR, clearByte)
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro ClearColorRam(clearByte) {
|
.macro ClearColorRam(clearByte) {
|
||||||
lda #clearByte
|
ClearChunks(Screen.COLOR_ADDR, clearByte)
|
||||||
ldx #0
|
|
||||||
!loop:
|
|
||||||
sta $D800, x
|
|
||||||
sta $D800 + $100, x
|
|
||||||
sta $D800 + $200, x
|
|
||||||
sta $D800 + $300, x
|
|
||||||
inx
|
|
||||||
bne.r !loop-
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetBorderColor(color) {
|
.macro SetBorderColor(color) {
|
||||||
lda #color
|
lda #color
|
||||||
sta $d020
|
sta $d020
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetBackgroundColor(color) {
|
.macro SetBackgroundColor(color) {
|
||||||
lda #color
|
lda #color
|
||||||
sta $d021
|
sta $d021
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetMultiColor1(color) {
|
.macro SetMultiColor1(color) {
|
||||||
lda #color
|
lda #color
|
||||||
sta $d022
|
sta $d022
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetMultiColor2(color) {
|
.macro SetMultiColor2(color) {
|
||||||
lda #color
|
lda #color
|
||||||
sta $d023
|
sta $d023
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetMultiColorMode() {
|
.macro SetMultiColorMode() {
|
||||||
lda $d016
|
lda $d016
|
||||||
ora #16
|
ora #16
|
||||||
sta $d016
|
sta $d016
|
||||||
}
|
}
|
||||||
|
|
||||||
.macro SetScrollMode() {
|
.macro SetScrollMode() {
|
||||||
lda $D016
|
lda $D016
|
||||||
eor #%00001000
|
eor #%00001000
|
||||||
sta $D016
|
sta $D016
|
||||||
}
|
}
|
||||||
|
|
||||||
.filenamespace Screen
|
.filenamespace Screen
|
||||||
|
|
||||||
|
|
||||||
// -----------------------
|
//------------------------------------------------------------------------------------
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
// -----------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
.label VIDEO_ADDR = $0400
|
||||||
.const VIDEO_ADDR = $0400
|
.label COLOR_ADDR = $D800
|
||||||
.const COLUMN_NUM = 40
|
.label COLUMN_NUM = 40
|
||||||
.const ROWS_NUM = 25
|
.label ROWS_NUM = 25
|
||||||
.const CR = $8e
|
.label CR = $8e
|
||||||
.const BS = $95
|
.label BS = $95
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,12 +103,12 @@ scrollUp: {
|
||||||
clone(VIDEO_ADDR+40, VIDEO_ADDR+(COLUMN_NUM*(ROWS_NUM)), VIDEO_ADDR)
|
clone(VIDEO_ADDR+40, VIDEO_ADDR+(COLUMN_NUM*(ROWS_NUM)), VIDEO_ADDR)
|
||||||
|
|
||||||
// clear last line
|
// clear last line
|
||||||
lda #32
|
lda #32
|
||||||
ldx #40
|
ldx #40
|
||||||
!:
|
!:
|
||||||
sta VIDEO_ADDR+(COLUMN_NUM*(ROWS_NUM-1)), x
|
sta VIDEO_ADDR+(COLUMN_NUM*(ROWS_NUM-1)), x
|
||||||
dex
|
dex
|
||||||
bne !-
|
bpl !- // x == -1
|
||||||
dec MemMap.SCREEN.CursorRow
|
dec MemMap.SCREEN.CursorRow
|
||||||
pla
|
pla
|
||||||
rts
|
rts
|
||||||
|
@ -130,6 +129,7 @@ printPetChar: {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
printChar: {
|
printChar: {
|
||||||
|
sei
|
||||||
stx MemMap.SCREEN.tempX
|
stx MemMap.SCREEN.tempX
|
||||||
cmp #CR
|
cmp #CR
|
||||||
bne.r !+
|
bne.r !+
|
||||||
|
@ -194,11 +194,11 @@ noEndOfLine:
|
||||||
pla
|
pla
|
||||||
|
|
||||||
// This is a backspace
|
// This is a backspace
|
||||||
cmp #BS
|
cmp #BS
|
||||||
bne !+
|
bne !+
|
||||||
lda #' '
|
lda #' '
|
||||||
sta (MemMap.SCREEN.TempVideoPointer), y
|
sta (MemMap.SCREEN.TempVideoPointer), y
|
||||||
jmp exit
|
jmp exit
|
||||||
|
|
||||||
!:
|
!:
|
||||||
// insert into screen
|
// insert into screen
|
||||||
|
@ -209,6 +209,7 @@ noEndOfLine:
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
ldx MemMap.SCREEN.tempX
|
ldx MemMap.SCREEN.tempX
|
||||||
|
cli
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,17 +224,17 @@ noEndOfLine:
|
||||||
// returned values: none
|
// returned values: none
|
||||||
// ——————————————————————————————————————————————————————
|
// ——————————————————————————————————————————————————————
|
||||||
print: {
|
print: {
|
||||||
ldy #$00
|
ldy #$00
|
||||||
sta MemMap.SCREEN.TempStringPointer
|
sta MemMap.SCREEN.TempStringPointer
|
||||||
stx MemMap.SCREEN.TempStringPointer+1
|
stx MemMap.SCREEN.TempStringPointer+1
|
||||||
printLoop:
|
printLoop:
|
||||||
lda (MemMap.SCREEN.TempStringPointer), y
|
lda (MemMap.SCREEN.TempStringPointer), y
|
||||||
cmp #0
|
cmp #0
|
||||||
beq exit
|
beq exit
|
||||||
jsr Screen.printChar
|
jsr Screen.printChar
|
||||||
jmp printLoop
|
jmp printLoop
|
||||||
exit:
|
exit:
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
51
shell.asm
51
shell.asm
|
@ -37,6 +37,41 @@ backspace: {
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exec: {
|
||||||
|
lda MemMap.SHELL.buffer // Check first char
|
||||||
|
cmp #'!'
|
||||||
|
beq stidExec // if ! is stid mon command
|
||||||
|
jmp wozExec // Otherwise exec Woz
|
||||||
|
// Expect exec functions to RTS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
stidExec: {
|
||||||
|
.break
|
||||||
|
ldy #1
|
||||||
|
|
||||||
|
lda MemMap.SHELL.buffer, y
|
||||||
|
|
||||||
|
cmp #'h'
|
||||||
|
beq cmdHelp
|
||||||
|
|
||||||
|
cmp #'r'
|
||||||
|
beq cmdReset
|
||||||
|
|
||||||
|
done:
|
||||||
|
rts
|
||||||
|
|
||||||
|
cmdHelp:
|
||||||
|
print(helpString)
|
||||||
|
jmp done
|
||||||
|
|
||||||
|
cmdReset:
|
||||||
|
jmp $fce2 // SYS 64738
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// WOZ MONITOR FLOW - FROM APPLE1
|
// WOZ MONITOR FLOW - FROM APPLE1
|
||||||
wozExec: {
|
wozExec: {
|
||||||
|
@ -194,4 +229,20 @@ PRHEX: and #%00001111 // Mask LSD for hex prin
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
* = * "Shell Data"
|
||||||
|
|
||||||
|
.encoding "screencode_mixed"
|
||||||
|
|
||||||
|
helpString:
|
||||||
|
.text "----------------------"
|
||||||
|
.byte $8e
|
||||||
|
.text "h : this help"
|
||||||
|
.byte $8e
|
||||||
|
.text "r : hard reset"
|
||||||
|
.byte $8e
|
||||||
|
.text "z : zero page params"
|
||||||
|
.byte $8e, 0
|
||||||
|
|
||||||
|
|
||||||
#import "mem_map.asm"
|
#import "mem_map.asm"
|
||||||
|
|
Loading…
Reference in New Issue