diff --git a/kernel/zxspectrum/jumps.asm b/kernel/zxspectrum/jumps.asm new file mode 100644 index 0000000..de70c46 --- /dev/null +++ b/kernel/zxspectrum/jumps.asm @@ -0,0 +1,30 @@ +; *** JUMP TABLE *** +; include the addresses of the actual table into user.h for userspace utilities + + jp strncmp + jp upcase + jp findchar + jp parseHex + jp parseDecimal + jp blkSel + jp blkSet + jp fsFindFN + jp fsOpen + jp fsGetB + jp fsPutB + jp fsSetSize + jp fsOn + jp fsIter + jp fsAlloc + jp fsHandle + jp fsblkTell + jp printstr + jp printnstr + jp printcrlf + jp stdioPutC + jp stdioGetC + jp stdioReadLine + jp _blkGetB + jp _blkPutB + jp _blkSeek + jp _blkTell diff --git a/kernel/zxspectrum/kbd.asm b/kernel/zxspectrum/kbd.asm new file mode 100644 index 0000000..3453b6d --- /dev/null +++ b/kernel/zxspectrum/kbd.asm @@ -0,0 +1,15 @@ +; the ZX Spectrum BASIC firmware scans the keyboard for ASCII codes on clock interrupts +; this routine just waits for a key and reads its value + +k_getc: +;ei +push hl +ld hl, 23611 ; ZXS_FLAGS +res 5, (hl) +.loop: +bit 5, (hl) ; pressed? +jr z, .loop +ld hl, 23560 ; ZXS_LASTK +ld a, (hl) +pop hl +ret diff --git a/kernel/zxspectrum/tapeblk.asm b/kernel/zxspectrum/tapeblk.asm new file mode 100644 index 0000000..fd39559 --- /dev/null +++ b/kernel/zxspectrum/tapeblk.asm @@ -0,0 +1,222 @@ +; tape blkdev read-only +; to be included as a kernel module. +; In the glue.asm devices list the PutB pointer has to be unsetZ + +; defines: +; tap_buffer = 256-byte tape loading buffer in RAM +; buf_pos = read position in the buffer +; crossing the buffer boundaries require loading or rewinding+loading +; tap_pos = previous read position of the block device, +; then the difference btw current and previous positions, both in EDLH format as throughout the kernel code + +tapeblk_init: +; initialized CFS and a placeholder 1-block, 1-byte file in the buffer +; the tape fs is not default, has to be mounted +ld hl, .plh +ld de, tap_buffer +ld bc, 6 +ldir +ret +.plh: +.db "CFS",1,1,0,'@' + +tapeGetB: +; it gets the new position in DE/HL, has to return value in A +push bc +push ix + +; First of all, is the difference between positions negative or positive? +push hl ; store the position +push de +ld ix, tap_pos ; previous + +push de ; working copy, higher bytes +ld e, (ix+2) ; lower bytes of previous position +ld d, (ix+3) +scf +ccf +sbc hl,de +ld (ix+6), l +ld (ix+7), h +pop hl +ld e, (ix+0) ; higher bytes +ld d, (ix+1) +sbc hl,de +ld (ix+4), l +ld (ix+5), h +jp nc, .tblk_posdif + +.tblk_negdif: +; at this point we have the negative difference +pop de ; restore the current position +pop hl +; store it as 'the previous' +ld (ix+0), e +ld (ix+1), d +ld (ix+2), l +ld (ix+3), h + +; let's set the buffer position while we're here +ld a, (buf_pos) +add a, (ix+6) ; l +; the difference bytes are negative, so e.g. add 255 = sub 1 +ld (buf_pos), a +; no carry would mean underflow in this case +jp nc, .tblk_rewind +; we now have a chance that the higher bytes are FF (due to lower CY) +xor a +dec a +and (ix+7) +and (ix+4) +and (ix+5) +cp 255 +jp z, .tblk_readbyte ; a negative difference within the buffer + +; we have to rewind the tape and load back to the current position, +; so it's safe to discard the difference and treat the current position as the positive difference + +.tblk_rewind: +; as we will rewind to zero, at least one additional block is to be loaded +xor a +inc h +cp h +jr nz, .tblk_store +inc de +.tblk_store: +ld (ix+4), e ; diff +ld (ix+5), d +ld (ix+6), l ; diff +ld (ix+7), h + +; purple border means 'rewind the tape and press enter' +di +ld a, 3 +out (254), a +.tblk_key: +ld a, 191 ; waiting for enter +in a,(254) +rra +jr c, .tblk_key +ei +jr .tblk_skip +; we don't have to set the buffer position, done it already + +.tblk_posdif: +; at this point we have the difference and know it is positive +pop de ; restore the current position +pop hl +; store it as 'the previous' +ld (ix+0), e +ld (ix+1), d +ld (ix+2), l +ld (ix+3), h + +.tblk_buffer: +; setting the buffer position for the positive difference +ld a, (buf_pos) +add a, (ix+6) ; l +ld (buf_pos), a +jr nc, .tblk_skip + +; now we increase the higher difference bytes due to overflow +xor a +inc (ix+7) ; h +cp (ix+7) +jr nz, .tblk_skip +inc (ix+4) ; e +cp (ix+4) +jr nz, .tblk_skip +inc (ix+5) ; d + +.tblk_skip: +; Now, how many tape blocks do we have to load before the target block appears in the buffer? +; it is shown by the 3 higher bytes of the difference +; We've just set them up for the positive difference case. + +; For the negative difference case, the L-byte has to be equal to the buf_pos we set earlier + +; (ix+7) H, (ix+4) E, (ix+5) D is now the counter for blocks to be loaded +; if it's 0, the block is already at the buffer and we don't have to load anything +xor a +or (ix+7) +or (ix+4) +or (ix+5) +jp z, .tblk_readbyte + +; well, let's play the tape +ld a, (ix+5) +ld b,a ; this is the outer cycle +inc b ; as we will djnz +ld a, (ix+7) +ld l, a ; lower byte of the inner counter +ld a, (ix+4) +ld h, a ; higher byte +dec hl ; as we know at this point that at least one block is to be loaded +ld c, 0 ; it's a 16-bit cycle flag used below +xor a +or h +or l +jp z, .tblk_load +ld c, 1 ; hl=nonzero + +.tblk_load: +push bc ; counters +push hl +ld ix, tap_buffer ; we don't need the ix value anymore +ld de, 256 +ld a, 255 +call t_load +pop hl +pop bc + +; counter +xor a +dec hl +or h +or l +jr nz, .tblk_ccheck +ld c, 0 ; on the next cycle, b has to be decremented +jr .tblk_load +.tblk_ccheck: +xor a +or c +jp nz, .tblk_load +inc c ; next 16-bit cycle +djnz .tblk_load + +.tblk_readbyte: +ld hl, tap_buffer +ld b, 0 +ld a, (buf_pos) +ld c, a +add hl,bc +ld a, (hl) ; here it is! +pop ix +pop bc +cp a +ret + +t_load: +push iy +ld iy, IYBAS +scf +; one can not call directly, as RST8 is then called upon break +inc d +ex af,af' +dec d +di +ld a, 15 +out (254), a +call 1378 ; jump into LD-BYTES +t_ldret: +ld a, (23624) ; restore border +and 0x38 +rrca +rrca +rrca +out (254),a +pop iy +ei +ret + +;end \ No newline at end of file diff --git a/kernel/zxspectrum/vid.asm b/kernel/zxspectrum/vid.asm new file mode 100644 index 0000000..f3ef9c7 --- /dev/null +++ b/kernel/zxspectrum/vid.asm @@ -0,0 +1,58 @@ +v_init: +call 3435 ; ZXS_CLS +ld a, 2 +call 5633 ; ZXS_STRM, current stream = 1, main screen +ret + +; the ZX Spectrum BASIC firmware puts the character in A into the current output stream by RST 16 + +v_putc: +; save all +push hl +push bc +push de +push af +push ix +push iy +ld iy, IYBAS ; restore IY for BASIC +; main +push af ; char +push bc ; curflag +push de ; coords +ld a, 22 ; AT_CTRL, screen position, 22x32 +rst 16 +pop de +ld a, d +push de +rst 16 +pop de +ld a, e +rst 16 +pop bc +xor a +cp c +jp z, .char +ld a, 18 ; FLASH_CTRL +rst 16 +xor a +inc a ; on +rst 16 +pop af +rst 16 +ld a, 18 ; FLASH_CTRL +rst 16 +xor a ; off +rst 16 +jp .rest +.char: +pop af +rst 16 +; restore and return +.rest: +pop iy +pop ix +pop af +pop de +pop bc +pop hl +ret