1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 07:38:06 +11:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Virgil Dupras
97dcad9b15 recipes/sms/kbd: use Collapse OS' AVR assembler 2020-02-26 23:10:43 -05:00
Virgil Dupras
64a54c72f8 Fix broken recipes 2020-02-26 21:44:37 -05:00
Virgil Dupras
92ddc7ebc1 recipes/trs80: use grid module
Not much of a gain in terms of usability (a bit of a loss in fact, things are
a bit slow and glitchy), but it's a necessary move if we want to use upcoming
grid-enabled userspace apps, such as a visual text editor.
2020-02-26 16:27:27 -05:00
Virgil Dupras
a442c46935 sms/vdp: highlight cursor with inverted palette 2020-02-26 09:43:50 -05:00
20 changed files with 280 additions and 119 deletions

View File

@ -628,19 +628,19 @@ _parseArgs:
_readBit:
ld a, 7
jr _readExpr
jp _readExpr
_readA6:
ld a, 0x3f
jr _readExpr
jp _readExpr
_readA5:
ld a, 0x1f
jr _readExpr
jp _readExpr
_readK8:
ld a, 0xff
jr _readExpr
jp _readExpr
_readDouble:
push de
@ -707,6 +707,12 @@ _readR5:
push de
ld a, (hl)
call upcase
cp 'X'
jr z, .rdXYZ
cp 'Y'
jr z, .rdXYZ
cp 'Z'
jr z, .rdXYZ
cp 'R'
jr nz, .end ; not a register
inc hl
@ -717,6 +723,34 @@ _readR5:
.end:
pop de
ret
.rdXYZ:
; First, let's get a base value, that is, (A-'X'+26)*2, because XL, our
; lowest register, is equivalent to r26.
sub 'X'
rla ; no carry from sub
add a, 26
ld d, a ; store that
inc hl
ld a, (hl)
call upcase
cp 'H'
jr nz, .skip1
; second char is 'H'? our value is +1
inc d
jr .skip2
.skip1:
cp 'L'
jr nz, .end ; not L either? then it's not good
.skip2:
; Good, we have our final value in D and we're almost sure it's a valid
; register. Our only check left is that the 3rd char is a null.
inc hl
ld a, (hl)
or a
jr nz, .end
; we're good
ld a, d
jr .end
; Put DE's LSB into A and, additionally, ensure that the new value is <=
; than what was previously in A.

View File

@ -1,12 +1,5 @@
; *** CPU registers aliases ***
.equ XH 27
.equ XL 26
.equ YH 29
.equ YL 28
.equ ZH 31
.equ ZL 30
.equ SREG_C 0 ; Carry Flag
.equ SREG_Z 1 ; Zero Flag
.equ SREG_N 2 ; Negative Flag

View File

@ -108,6 +108,9 @@ void create_window()
xcb_map_window(conn, win);
}
// To make things simple with X11, we only support monochrome display, which is
// inverted: As soon as the color of the pixel is non-black, we show a black
// pixel. If the pixel is white, we show black.
void draw_pixels()
{
xcb_get_geometry_reply_t *geom;

View File

@ -51,6 +51,7 @@ void vdp_data_wr(VDP *vdp, uint8_t val)
}
}
// Returns a 8-bit RGB value (0b00bbggrr)
uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
{
if (x >= VDP_SCREENW) {
@ -63,6 +64,8 @@ uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
uint16_t offset = 0x3800 + ((y/8) << 6) + ((x/8) << 1);
uint16_t tableval = vdp->vram[offset] + (vdp->vram[offset+1] << 8);
uint16_t tilenum = tableval & 0x1ff;
// is palette select bit on? if yes, use sprite palette instead
uint8_t palettemod = tableval & 0x800 ? 0x10 : 0;
// tile offset this time. Each tile is 0x20 bytes long.
offset = tilenum * 0x20;
// Each 4 byte is a row. Find row first.
@ -70,8 +73,10 @@ uint8_t vdp_pixel(VDP *vdp, uint16_t x, uint16_t y)
uint8_t bitnum = 7 - (x%8);
// Now, let's compose the result by pushing the right bit of our 4 bytes
// into our result.
return ((vdp->vram[offset] >> bitnum) & 1) + \
uint8_t palette_id = ((vdp->vram[offset] >> bitnum) & 1) + \
(((vdp->vram[offset+1] >> bitnum) & 1) << 1) + \
(((vdp->vram[offset+2] >> bitnum) & 1) << 2) + \
(((vdp->vram[offset+3] >> bitnum) & 1) << 3);
uint8_t rgb = vdp->vram[0x4000+palettemod+palette_id];
return rgb;
}

View File

@ -12,8 +12,10 @@
; can access those cells by their (X, Y) address. In addition to this, we have
; the concept of an active cursor, which will be indicated visually if possible.
;
; Additionally, this module provides a PutC routine, suitable for plugging into
; stdio.
; This module provides PutC and GetC routines, suitable for plugging into stdio.
; PutC, for obvious reasons, GetC, for less obvious reasons: We need to wrap
; GetC because we need to update the cursor before calling actual GetC, but
; also, because we need to know when a bulk update ends.
;
; *** Defines ***
;
@ -21,7 +23,9 @@
; GRID_ROWS: Number of rows in the grid
; GRID_SETCELL: Pointer to routine that sets cell at row D and column E with
; character in A. If C is nonzero, this cell must be displayed,
; if possible, as the cursor.
; if possible, as the cursor. This routine is never called with
; A < 0x20.
; GRID_GETC: Routine that gridGetC will wrap around.
;
; *** Consts ***
.equ GRID_SIZE GRID_COLS*GRID_ROWS
@ -31,6 +35,10 @@
.equ GRID_CURX GRID_RAMSTART
; Cursor's row
.equ GRID_CURY @+1
; Whether we scrolled recently. We don't refresh the screen immediately when
; scrolling in case we have many lines being spit at once (refreshing the
; display is then very slow). Instead, we wait until the next gridGetC call
.equ GRID_SCROLLED @+1
; Grid's in-memory buffer of the contents on screen. Because we always push to
; display right after a change, this is almost always going to be a correct
; representation of on-screen display.
@ -53,7 +61,7 @@ _gridPlaceCell:
ld hl, GRID_BUF
ld a, d
or a
ret z
jr z, .setcol
push de ; --> lvl 1
ld de, GRID_COLS
.loop:
@ -61,10 +69,18 @@ _gridPlaceCell:
dec a
jr nz, .loop
pop de ; <-- lvl 1
.setcol:
; We're at the proper row, now let's advance to cell
ld a, e
jp addHL
; Ensure that A >= 0x20
_gridAdjustA:
cp 0x20
ret nc
ld a, 0x20
ret
; Push row D in the buffer onto the screen.
gridPushRow:
push af
@ -78,6 +94,7 @@ gridPushRow:
ld b, GRID_COLS
.loop:
ld a, (hl)
call _gridAdjustA
; A, C, D and E have proper values
call GRID_SETCELL
inc hl
@ -98,11 +115,10 @@ gridClrRow:
push hl
ld e, 0
call _gridPlaceCell
xor a
ld a, ' '
ld b, GRID_COLS
call fill
call gridPushRow
pop hl
pop de
pop bc
@ -119,7 +135,7 @@ gridPushScr:
pop de
ret
; Set character under cursor to A
; Set character under cursor to A. C is passed to GRID_SETCELL as-is.
gridSetCur:
push de
push hl
@ -131,17 +147,34 @@ gridSetCur:
call _gridPlaceCell
pop af \ push af ; <--> lvl 1
ld (hl), a
call _gridAdjustA
call GRID_SETCELL
pop af ; <-- lvl 1
pop hl
pop de
ret
; Call gridSetCur with C = 1.
gridSetCurH:
push bc
ld c, 1
call gridSetCur
pop bc
ret
; Call gridSetCur with C = 0.
gridSetCurL:
push bc
ld c, 0
call gridSetCur
pop bc
ret
; Clear character under cursor
gridClrCur:
push af
ld a, ' '
call gridSetCur
call gridSetCurL
pop af
ret
@ -150,19 +183,10 @@ gridLF:
push de
push af
ld a, (GRID_CURY)
call .incA
ld d, a
call gridClrRow
ld (GRID_CURY), a
xor a
ld (GRID_CURX), a
pop af
pop de
ret
.incA:
; increase A
inc a
cp GRID_ROWS
ret nz ; no rollover
jr nz, .noscroll
; bottom reached, stay on last line and scroll screen
push hl
push de
@ -171,11 +195,21 @@ gridLF:
ld hl, GRID_BUF+GRID_COLS
ld bc, GRID_SIZE-GRID_COLS
ldir
ld hl, GRID_SCROLLED
inc (hl) ; mark as scrolled
pop bc
pop de
pop hl
call gridPushScr
dec a
.noscroll:
; A has been increased properly
ld d, a
call gridClrRow
ld (GRID_CURY), a
xor a
ld (GRID_CURX), a
pop af
pop de
ret
gridBS:
@ -210,7 +244,7 @@ gridPutC:
cp ' '
ret c ; ignore unhandled control characters
call gridSetCur
call gridSetCurL
push af ; --> lvl 1
; Move cursor
ld a, (GRID_CURX)
@ -226,3 +260,16 @@ gridPutC:
call gridLF
pop af ; <-- lvl 1
ret
gridGetC:
ld a, (GRID_SCROLLED)
or a
jr z, .nopush
; We've scrolled recently, update screen
xor a
ld (GRID_SCROLLED), a
call gridPushScr
.nopush:
ld a, ' '
call gridSetCurH
jp GRID_GETC

View File

@ -181,7 +181,7 @@ padGetC:
; no action button pressed, but because our pad status changed, update
; VDP before looping.
ld a, (PAD_SELCHR)
call gridSetCur
call gridSetCurH
jp padGetC
.return:
ld a, LF
@ -190,7 +190,7 @@ padGetC:
.advance:
ld a, (PAD_SELCHR)
; Z was already set from previous BIT instruction
ret
jp gridSetCurL
.backspace:
ld a, BS
; Z was already set from previous BIT instruction

View File

@ -23,8 +23,8 @@
; *** Code ***
vdpInit:
ld hl, vdpInitData
ld b, vdpInitDataEnd-vdpInitData
ld hl, .initData
ld b, .initDataEnd-.initData
ld c, VDP_CTLPORT
otir
@ -47,10 +47,10 @@ vdpInit:
out (VDP_CTLPORT), a
ld a, 0xc0
out (VDP_CTLPORT), a
xor a ; palette 0: black
out (VDP_DATAPORT), a
ld a, 0x3f ; palette 1: white
out (VDP_DATAPORT), a
ld hl, .paletteData
ld b, .paletteDataEnd-.paletteData
ld c, VDP_DATAPORT
otir
; Define tiles
xor a
@ -97,6 +97,28 @@ vdpInit:
out (VDP_CTLPORT), a
ret
; VDP initialisation data
.initData:
; 0x8x == set register X
.db 0b00000100, 0x80 ; Bit 2: Select mode 4
.db 0b00000000, 0x81
.db 0b11111111, 0x82 ; Name table: 0x3800
.db 0b11111111, 0x85 ; Sprite table: 0x3f00
.db 0b11111111, 0x86 ; sprite use tiles from 0x2000
.db 0b11111111, 0x87 ; Border uses palette 0xf
.db 0b00000000, 0x88 ; BG X scroll
.db 0b00000000, 0x89 ; BG Y scroll
.db 0b11111111, 0x8a ; Line counter (why have this?)
.initDataEnd:
.paletteData:
; BG palette
.db 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
; Sprite palette (inverted colors)
.db 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.paletteDataEnd:
; Convert ASCII char in A into a tile index corresponding to that character.
; When a character is unknown, returns 0x5e (a '~' char).
vdpConv:
@ -108,7 +130,8 @@ vdpConv:
ld a, 0x5e
ret
; grid routine. Sets cell at row D and column E to character A
; grid routine. Sets cell at row D and column E to character A. If C is one, we
; use the sprite palette.
vdpSetCell:
call vdpConv
; store A away
@ -141,18 +164,11 @@ vdpSetCell:
; We're ready to send our data now. Let's go
ex af, af'
out (VDP_DATAPORT), a
; Palette select is on bit 3 of MSB
ld a, 1
and c
rla \ rla \ rla
out (VDP_DATAPORT), a
ret
; VDP initialisation data
vdpInitData:
; 0x8x == set register X
.db 0b00000100, 0x80 ; Bit 2: Select mode 4
.db 0b00000000, 0x81
.db 0b11111111, 0x82 ; Name table: 0x3800
.db 0b11111111, 0x85 ; Sprite table: 0x3f00
.db 0b11111111, 0x86 ; sprite use tiles from 0x2000
.db 0b11111111, 0x87 ; Border uses palette 0xf
.db 0b00000000, 0x88 ; BG X scroll
.db 0b00000000, 0x89 ; BG Y scroll
.db 0b11111111, 0x8a ; Line counter (why have this?)
vdpInitDataEnd:

View File

@ -1,7 +1,9 @@
; vid - TRS-80's video
;
; Implement PutC using TRS-80's SVC calls so that character it put on video
; display.
; Implement PutC and GRID_SETCELL using TRS-80's SVC calls.
.equ TRS80_COLS 80
.equ TRS80_ROWS 24
trs80PutC:
push af
@ -14,3 +16,44 @@ trs80PutC:
pop bc
pop af
ret
trs80SetCell:
push af
push bc
push hl ; HL altered by @VDCTL
push de ; DE altered by @VDCTL
ex de, hl
bit 0, c
ld c, a ; save A now
jr z, .skip ; Z from BIT above. cursor not set
; set cursor
ld a, 0x0f ; @VDCTL
ld b, 3 ; move cursor fn
rst 0x28
; HL altered.
; Our Row/Col is our currently-pushed DE value. Let's take advantage of
; that.
pop hl \ push hl ; HL altered. bring back from stack
.skip:
ld a, 0x0f ; @VDCTL
ld b, 2 ; display char
rst 0x28
pop de
pop hl
pop bc
pop af
ret
; This is a much faster version of gridPushScr. Use it in your glue code, but
; you need to set HL to GRID_BUF first.
trs80PushScr:
push af
push bc
ld a, 0x0f ; @VDCTL
ld b, 5 ; move from RAM to vid
; HL is already set by caller
rst 0x28
pop bc
pop af
cp a ; ensure Z
ret

View File

@ -21,6 +21,7 @@
jp fsOpen
jp fsGetB
jp printstr
jp printcrlf
jp _blkGetB
jp _blkPutB
jp _blkSeek
@ -28,12 +29,15 @@
jp sdcGetB
jp sdcPutB
jp blkGetB
jp stdioPutC
; interrupt hook
.fill 0x38-$
jp aciaInt
; *** cont. ***
jp stdioPutC
.inc "err.h"
.inc "ascii.h"
.inc "blkdev.h"

View File

@ -10,6 +10,7 @@
.equ fsOpen @+3
.equ fsGetB @+3
.equ printstr @+3
.equ printcrlf @+3
.equ _blkGetB @+3
.equ _blkPutB @+3
.equ _blkSeek @+3
@ -17,4 +18,6 @@
.equ sdcGetB @+3
.equ sdcPutB @+3
.equ blkGetB @+3
.equ stdioPutC @+3
; *** cont. ***
.equ stdioPutC 0x3b

View File

@ -21,10 +21,11 @@
.equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell
.equ GRID_GETC padGetC
.inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC padGetC
.equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC
.inc "stdio.asm"

View File

@ -1,11 +1,13 @@
PROGNAME = ps2ctl
AVRDUDEMCU ?= t45
AVRDUDEARGS ?= -c usbtiny -P usb
TARGETS = $(PROGNAME).hex os.sms
TARGETS = $(PROGNAME).bin os.sms
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
AVRA = $(BASEDIR)/emul/zasm/avra
AVRINC = $(BASEDIR)/avr
# Rules
@ -14,14 +16,14 @@ APPS = $(BASEDIR)/apps
all: $(TARGETS)
@echo Done!
send: $(PROGNAME).hex
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
send: $(PROGNAME).bin
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).bin
$(PROGNAME).hex: $(PROGNAME).asm
avra -o $@ $(PROGNAME).asm
$(PROGNAME).bin: $(PROGNAME).asm
$(AVRA) $(AVRINC) < $(PROGNAME).asm > $@
os.sms: glue.asm
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
clean:
rm -f $(TARGETS) *.eep.hex *.obj os.bin
rm -f $(TARGETS)

View File

@ -55,7 +55,6 @@ either the low or high bits.
* 74xx157 (multiplexer)
* A NOR SR-latch. I used a 4043.
* Proto board, wires, IC sockets, etc.
* [AVRA][avra]
## Historical note
@ -114,4 +113,3 @@ Just hook it on. I've tried it, it works.
Did you get there? Feels pretty cool huh?
[rc2014-ps2]: ../../rc2014/ps2
[avra]: https://github.com/hsoft/avra

View File

@ -23,10 +23,11 @@
.equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell
.equ GRID_GETC kbdGetC
.inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC kbdGetC
.equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC
.inc "stdio.asm"

View File

@ -1,5 +1,3 @@
.include "tn45def.inc"
; Receives keystrokes from PS/2 keyboard and send them to the '164. On the PS/2
; side, it works the same way as the controller in the rc2014/ps2 recipe.
; However, in this case, what we have on the other side isn't a z80 bus, it's
@ -30,17 +28,22 @@
; written.
; Z: pointer to the next scan code to push to the 595
;
.inc "avr.h"
.inc "tn254585.h"
.inc "tn45.h"
; *** Constants ***
.equ CLK = PINB2
.equ DATA = PINB1
.equ CP = PINB3
.equ CLK 2 ; Port B
.equ DATA 1 ; Port B
.equ CP 3 ; Port B
; SR-Latch's Q pin
.equ LQ = PINB0
.equ LQ 0 ; Port B
; SR-Latch's R pin
.equ LR = PINB4
.equ LR 4 ; Port B
; init value for TCNT0 so that overflow occurs in 100us
.equ TIMER_INITVAL = 0x100-100
.equ TIMER_INITVAL 0x100-100
; *** Code ***
@ -56,9 +59,9 @@ hdlINT0:
reti
main:
ldi r16, low(RAMEND)
ldi r16, RAMEND&0xff
out SPL, r16
ldi r16, high(RAMEND)
ldi r16, RAMEND}8
out SPH, r16
; init variables
@ -67,23 +70,23 @@ main:
; Setup int0
; INT0, falling edge
ldi r16, (1<<ISC01)
ldi r16, 0x02 ; ISC01
out MCUCR, r16
; Enable INT0
ldi r16, (1<<INT0)
ldi r16, 0x40 ; INT0
out GIMSK, r16
; Setup buffer
clr YH
ldi YL, low(SRAM_START)
ldi YL, SRAM_START&0xff
clr ZH
ldi ZL, low(SRAM_START)
ldi ZL, SRAM_START&0xff
; Setup timer. We use the timer to clear up "processbit" registers after
; 100us without a clock. This allows us to start the next frame in a
; fresh state. at 1MHZ, no prescaling is necessary. Each TCNT0 tick is
; already 1us long.
ldi r16, (1<<CS00) ; no prescaler
ldi r16, 0x01 ; CS00 - no prescaler
out TCCR0B, r16
; init DDRB
@ -101,7 +104,7 @@ loop:
; nothing to do. Before looping, let's check if our communication timer
; overflowed.
in r16, TIFR
sbrc r16, TOV0
sbrc r16, 1 ; TOV0
rjmp processbitReset ; Timer0 overflow? reset processbit
; Nothing to do for real.
@ -220,7 +223,7 @@ sendTo164Loop:
resetTimer:
ldi r16, TIMER_INITVAL
out TCNT0, r16
ldi r16, (1<<TOV0)
ldi r16, 0x02 ; TOV0
out TIFR, r16
ret
@ -237,8 +240,8 @@ sendToPS2:
; Wait until the timer overflows
in r16, TIFR
sbrs r16, TOV0
rjmp PC-2
sbrs r16, 1 ; TOV0
rjmp $-4
; Good, 100us passed.
; Pull Data low, that's our start bit.
@ -258,7 +261,7 @@ sendToPS2:
sendToPS2Loop:
; Wait for CLK to go low
sbic PINB, CLK
rjmp PC-1
rjmp $-2
; set up DATA
cbi PORTB, DATA
@ -268,7 +271,7 @@ sendToPS2Loop:
; Wait for CLK to go high
sbis PINB, CLK
rjmp PC-1
rjmp $-2
dec r16
brne sendToPS2Loop ; not zero? loop
@ -279,7 +282,7 @@ sendToPS2Loop:
; Wait for CLK to go low
sbic PINB, CLK
rjmp PC-1
rjmp $-2
; set parity bit
cbi PORTB, DATA
@ -288,22 +291,22 @@ sendToPS2Loop:
; Wait for CLK to go high
sbis PINB, CLK
rjmp PC-1
rjmp $-2
; Wait for CLK to go low
sbic PINB, CLK
rjmp PC-1
rjmp $-2
; We can now release the DATA line
cbi DDRB, DATA
; Wait for DATA to go low. That's our ACK
sbic PINB, DATA
rjmp PC-1
rjmp $-2
; Wait for CLK to go low
sbic PINB, CLK
rjmp PC-1
rjmp $-2
; We're finished! Enable INT0, reset timer, everything back to normal!
rcall resetTimer
@ -314,21 +317,21 @@ sendToPS2Loop:
; Check that Y is within bounds, reset to SRAM_START if not.
checkBoundsY:
tst YL
breq PC+2
breq $+4
ret ; not zero, nothing to do
; YL is zero. Reset Y
clr YH
ldi YL, low(SRAM_START)
ldi YL, SRAM_START&0xff
ret
; Check that Z is within bounds, reset to SRAM_START if not.
checkBoundsZ:
tst ZL
breq PC+2
breq $+4
ret ; not zero, nothing to do
; ZL is zero. Reset Z
clr ZH
ldi ZL, low(SRAM_START)
ldi ZL, SRAM_START&0xff
ret
; Counts the number of 1s in r19 and set r16 to 1 if there's an even number of
@ -336,10 +339,10 @@ checkBoundsZ:
checkParity:
ldi r16, 1
lsr r19
brcc PC+2 ; Carry unset? skip next
brcc $+4 ; Carry unset? skip next
inc r16 ; Carry set? We had a 1
tst r19 ; is r19 zero yet?
brne checkParity+1 ; no? loop and skip first LDI
brne checkParity+2 ; no? loop and skip first LDI
andi r16, 0x1 ; Sets Z accordingly
ret

View File

@ -52,10 +52,11 @@
.equ GRID_COLS VDP_COLS
.equ GRID_ROWS VDP_ROWS
.equ GRID_SETCELL vdpSetCell
.equ GRID_GETC kbdGetC
.inc "grid.asm"
.equ STDIO_RAMSTART GRID_RAMEND
.equ STDIO_GETC kbdGetC
.equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC
.inc "stdio.asm"

View File

@ -2,17 +2,13 @@
.equ RAMEND 0xcfff
; Address of the *CL driver. Same as in recv.asm
.equ COM_DRV_ADDR 0x0238
; in sync with user.h. Last BAS_RAMEND: 0x5705
.equ USER_CODE 0x5800
; in sync with user.h. Last BAS_RAMEND: 0x600b
.equ USER_CODE 0x6100
; Free memory in TRSDOS starts at 0x3000
.org 0x3000
jp init
; The TRS-80 generates a double line feed if we give it both CR and LF.
; Has to be defined before the jump table.
.equ printcrlf printcr
; *** Jump Table ***
jp strncmp
jp upcase
@ -45,7 +41,14 @@
.equ FLOPPY_RAMSTART RAMSTART
.inc "trs80/floppy.asm"
.equ BLOCKDEV_RAMSTART FLOPPY_RAMEND
.equ GRID_RAMSTART FLOPPY_RAMEND
.equ GRID_ROWS TRS80_ROWS
.equ GRID_COLS TRS80_COLS
.equ GRID_SETCELL trs80SetCell
.equ GRID_GETC trs80GetC
.equ gridPushScr fastPushScr
.inc "grid.asm"
.equ BLOCKDEV_RAMSTART GRID_RAMEND
.equ BLOCKDEV_COUNT 3
.inc "blockdev.asm"
; List of devices
@ -54,8 +57,9 @@
.dw blk2GetB, blk2PutB
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC trs80GetC
.equ STDIO_PUTC trs80PutC
.equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC
.equ STDIO_SETCUR gridSetCurH
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
@ -91,6 +95,7 @@
init:
ld sp, RAMEND
call gridInit
call floppyInit
call fsInit
call basInit
@ -103,13 +108,6 @@ init:
jp basStart
printcr:
push af
ld a, CR
call STDIO_PUTC
pop af
ret
; Receive a byte from *cl and put it in A.
; Returns A > 0xff when receiving the last byte
recvCmd:
@ -172,6 +170,13 @@ basFindCmdExtra:
.dw recvCmd
.db 0xff ; end of table
fastPushScr:
push hl
ld hl, GRID_BUF
call trs80PushScr
pop hl
ret
; *** blkdev 1: file handle 0 ***
blk1GetB:

View File

@ -1,4 +1,4 @@
.org 0x5800
.org 0x6100
.equ strncmp 0x3003
.equ upcase @+3
.equ findchar @+3

View File

@ -24,3 +24,5 @@ jmp bar
mov r6, r30
lsl r3
tst r12
clr YH
clr r29

Binary file not shown.