From 905a5b9183d048c474e69dfacd2de9aee0c76811 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sun, 16 Mar 2025 23:55:33 +0100 Subject: [PATCH 1/3] feat: add random.bas library --- src/lib/arch/zx48k/stdlib/random.bas | 57 +++++++++++++++++++++++++++ src/lib/arch/zxnext/stdlib/random.bas | 57 +++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 src/lib/arch/zx48k/stdlib/random.bas create mode 100644 src/lib/arch/zxnext/stdlib/random.bas diff --git a/src/lib/arch/zx48k/stdlib/random.bas b/src/lib/arch/zx48k/stdlib/random.bas new file mode 100644 index 000000000..06ec92bf3 --- /dev/null +++ b/src/lib/arch/zx48k/stdlib/random.bas @@ -0,0 +1,57 @@ +' ---------------------------------------------------------------- +' This file is released under the MIT License +' +' Copyleft (k) 2025 +' by Jose Rodriguez-Rosa (a.k.a. Boriel) +' ---------------------------------------------------------------- + +#pragma once +#pragma push(case_insensitive) +#pragma case_insensitive = TRUE + +function fastcall randInt() as ULong ' Returns a random ULong + asm + push namespace core + call RAND + pop namespace + end asm +end function + + +Function fastcall randFixed() as Fixed ' Returns a random Fixed + Asm + push namespace core + call RAND + pop namespace + End Asm +End Function + + +Function fastcall randomLimit(limit as uByte) as uByte + Asm + push namespace core + PROC + and a + ret z ; Input zero, output zero. + ld b, a ; Save A + ld c,255 + 1: + rla + jr c, 2f + rr c + jp 1b ; loop back until we find a bit. + 2: + push bc + call RAND + pop bc + and c + cp b + ret z + jr nc, 2b + ENDP + pop namespace + End Asm +End Function + +#pragma pop(case_insensitive) +#require "random.asm" diff --git a/src/lib/arch/zxnext/stdlib/random.bas b/src/lib/arch/zxnext/stdlib/random.bas new file mode 100644 index 000000000..06ec92bf3 --- /dev/null +++ b/src/lib/arch/zxnext/stdlib/random.bas @@ -0,0 +1,57 @@ +' ---------------------------------------------------------------- +' This file is released under the MIT License +' +' Copyleft (k) 2025 +' by Jose Rodriguez-Rosa (a.k.a. Boriel) +' ---------------------------------------------------------------- + +#pragma once +#pragma push(case_insensitive) +#pragma case_insensitive = TRUE + +function fastcall randInt() as ULong ' Returns a random ULong + asm + push namespace core + call RAND + pop namespace + end asm +end function + + +Function fastcall randFixed() as Fixed ' Returns a random Fixed + Asm + push namespace core + call RAND + pop namespace + End Asm +End Function + + +Function fastcall randomLimit(limit as uByte) as uByte + Asm + push namespace core + PROC + and a + ret z ; Input zero, output zero. + ld b, a ; Save A + ld c,255 + 1: + rla + jr c, 2f + rr c + jp 1b ; loop back until we find a bit. + 2: + push bc + call RAND + pop bc + and c + cp b + ret z + jr nc, 2b + ENDP + pop namespace + End Asm +End Function + +#pragma pop(case_insensitive) +#require "random.asm" From 66d6100a728ba9e924c2c3958315098615261ab2 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Mon, 17 Mar 2025 00:07:26 +0100 Subject: [PATCH 2/3] refact: improve rand routine Instead of geting every byte from the lower byte of each 32 bit numbers (which require 4 loops), use just the 32 bit directly. Note this might reduce randomness and might be crypthograpycally less secure... (which for the Z80 is of little importance... I guess). --- src/lib/arch/zx48k/runtime/random.asm | 15 ++------------- src/lib/arch/zx48k/stdlib/random.bas | 2 -- src/lib/arch/zxnext/runtime/random.asm | 15 ++------------- src/lib/arch/zxnext/stdlib/random.bas | 2 -- 4 files changed, 4 insertions(+), 30 deletions(-) diff --git a/src/lib/arch/zx48k/runtime/random.asm b/src/lib/arch/zx48k/runtime/random.asm index ef58fec0d..0e80a4b04 100644 --- a/src/lib/arch/zx48k/runtime/random.asm +++ b/src/lib/arch/zx48k/runtime/random.asm @@ -31,17 +31,14 @@ TAKE_FRAMES: FRAMES EQU 23672 ENDP -RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits +RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -59,14 +56,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP diff --git a/src/lib/arch/zx48k/stdlib/random.bas b/src/lib/arch/zx48k/stdlib/random.bas index 06ec92bf3..38232361e 100644 --- a/src/lib/arch/zx48k/stdlib/random.bas +++ b/src/lib/arch/zx48k/stdlib/random.bas @@ -41,9 +41,7 @@ Function fastcall randomLimit(limit as uByte) as uByte rr c jp 1b ; loop back until we find a bit. 2: - push bc call RAND - pop bc and c cp b ret z diff --git a/src/lib/arch/zxnext/runtime/random.asm b/src/lib/arch/zxnext/runtime/random.asm index ef58fec0d..0e80a4b04 100644 --- a/src/lib/arch/zxnext/runtime/random.asm +++ b/src/lib/arch/zxnext/runtime/random.asm @@ -31,17 +31,14 @@ TAKE_FRAMES: FRAMES EQU 23672 ENDP -RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits +RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -59,14 +56,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP diff --git a/src/lib/arch/zxnext/stdlib/random.bas b/src/lib/arch/zxnext/stdlib/random.bas index 06ec92bf3..38232361e 100644 --- a/src/lib/arch/zxnext/stdlib/random.bas +++ b/src/lib/arch/zxnext/stdlib/random.bas @@ -41,9 +41,7 @@ Function fastcall randomLimit(limit as uByte) as uByte rr c jp 1b ; loop back until we find a bit. 2: - push bc call RAND - pop bc and c cp b ret z From 37eaebda14dd19934d5b700ab8891ead081d111e Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Sat, 22 Mar 2025 19:51:02 +0100 Subject: [PATCH 3/3] test: update tests --- tests/functional/arch/zx48k/mcleod.asm | 15 +------ tests/functional/arch/zx48k/opt4_keepix.asm | 47 ++++++++------------- tests/functional/arch/zx48k/randomize.asm | 19 ++------- tests/functional/arch/zx48k/rnd.asm | 23 +++------- 4 files changed, 30 insertions(+), 74 deletions(-) diff --git a/tests/functional/arch/zx48k/mcleod.asm b/tests/functional/arch/zx48k/mcleod.asm index a035f917a..0c3ac54b9 100644 --- a/tests/functional/arch/zx48k/mcleod.asm +++ b/tests/functional/arch/zx48k/mcleod.asm @@ -232,15 +232,12 @@ TAKE_FRAMES: ret FRAMES EQU 23672 ENDP - RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits + RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -258,14 +255,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP RND: diff --git a/tests/functional/arch/zx48k/opt4_keepix.asm b/tests/functional/arch/zx48k/opt4_keepix.asm index f4b40371e..ab96b42ee 100644 --- a/tests/functional/arch/zx48k/opt4_keepix.asm +++ b/tests/functional/arch/zx48k/opt4_keepix.asm @@ -71,8 +71,8 @@ _test__leave: pop ix ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/addf.asm" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/stackf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/addf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/stackf.asm" ; ------------------------------------------------------------- ; Functions to manage FP-Stack of the ZX Spectrum ROM CALC ; ------------------------------------------------------------- @@ -111,7 +111,7 @@ __FPSTACK_I16: ; Pushes 16 bits integer in HL into the FP ROM STACK ld b, a jp __FPSTACK_PUSH pop namespace -#line 2 "/zxbasic/src/arch/zx48k/library-asm/addf.asm" +#line 2 "/zxbasic/src/lib/arch/zx48k/runtime/arith/addf.asm" ; ------------------------------------------------------------- ; Floating point library using the FP ROM Calculator (ZX 48K) ; All of them uses A EDCB registers as 1st paramter. @@ -129,8 +129,8 @@ __ADDF: ; Addition defb 38h; ; END CALC jp __FPSTACK_POP pop namespace -#line 53 "opt4_keepix.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/mulf.asm" +#line 53 "arch/zx48k/opt4_keepix.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/arith/mulf.asm" ; ------------------------------------------------------------- ; Floating point library using the FP ROM Calculator (ZX 48K) ; All of them uses A EDCB registers as 1st paramter. @@ -148,13 +148,13 @@ __MULF: ; Multiplication defb 38h; ; END CALC jp __FPSTACK_POP pop namespace -#line 54 "opt4_keepix.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" +#line 54 "arch/zx48k/opt4_keepix.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/ploadf.asm" ; Parameter / Local var load ; A => Offset ; IX = Stack Frame ; RESULT: HL => IX + DE -#line 1 "/zxbasic/src/arch/zx48k/library-asm/iloadf.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/iloadf.asm" ; __FASTCALL__ routine which ; loads a 40 bits floating point into A ED CB ; stored at position pointed by POINTER HL @@ -181,7 +181,7 @@ __LOADF: ; Loads a 40 bits FP number from address pointed by HL ld b, (hl) ret pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/ploadf.asm" +#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/ploadf.asm" push namespace core __PLOADF: push ix @@ -189,13 +189,13 @@ __PLOADF: add hl, de jp __LOADF pop namespace -#line 55 "opt4_keepix.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/pstoref.asm" +#line 55 "arch/zx48k/opt4_keepix.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/pstoref.asm" ; Stores FP number in A ED CB at location HL+IX ; HL = Offset ; IX = Stack Frame ; A ED CB = FP Number -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -223,7 +223,7 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 7 "/zxbasic/src/arch/zx48k/library-asm/pstoref.asm" +#line 7 "/zxbasic/src/lib/arch/zx48k/runtime/pstoref.asm" ; Stored a float number in A ED CB into the address pointed by IX + HL push namespace core __PSTOREF: @@ -235,8 +235,8 @@ __PSTOREF: pop de jp __STOREF pop namespace -#line 56 "opt4_keepix.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/random.asm" +#line 56 "arch/zx48k/opt4_keepix.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/random.asm" ; RANDOM functions push namespace core RANDOMIZE: @@ -262,15 +262,12 @@ TAKE_FRAMES: ret FRAMES EQU 23672 ENDP - RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits + RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -288,14 +285,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP RND: @@ -336,5 +325,5 @@ RND_LOOP: ret ENDP pop namespace -#line 57 "opt4_keepix.bas" +#line 57 "arch/zx48k/opt4_keepix.bas" END diff --git a/tests/functional/arch/zx48k/randomize.asm b/tests/functional/arch/zx48k/randomize.asm index 1954d1d80..4df1eb482 100644 --- a/tests/functional/arch/zx48k/randomize.asm +++ b/tests/functional/arch/zx48k/randomize.asm @@ -41,7 +41,7 @@ ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/random.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/random.asm" ; RANDOM functions push namespace core RANDOMIZE: @@ -67,15 +67,12 @@ TAKE_FRAMES: ret FRAMES EQU 23672 ENDP - RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits + RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -93,14 +90,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP RND: @@ -141,5 +130,5 @@ RND_LOOP: ret ENDP pop namespace -#line 23 "randomize.bas" +#line 23 "arch/zx48k/randomize.bas" END diff --git a/tests/functional/arch/zx48k/rnd.asm b/tests/functional/arch/zx48k/rnd.asm index b5c84c1cc..bdf030c80 100644 --- a/tests/functional/arch/zx48k/rnd.asm +++ b/tests/functional/arch/zx48k/rnd.asm @@ -43,7 +43,7 @@ _a: ei ret ;; --- end of user code --- -#line 1 "/zxbasic/src/arch/zx48k/library-asm/random.asm" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/random.asm" ; RANDOM functions push namespace core RANDOMIZE: @@ -69,15 +69,12 @@ TAKE_FRAMES: ret FRAMES EQU 23672 ENDP - RANDOM_SEED_HIGH EQU RAND+6 ; RANDOM seed, 16 higher bits + RANDOM_SEED_HIGH EQU RAND+1 ; RANDOM seed, 16 higher bits RANDOM_SEED_LOW EQU 23670 ; RANDOM seed, 16 lower bits RAND: PROC - LOCAL RAND_LOOP - ld b, 4 -RAND_LOOP: - ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld de,0C0DEh ; yw -> zt + ld hl,(RANDOM_SEED_LOW) ; xz -> yw ld (RANDOM_SEED_LOW),de ; x = y, z = w ld a,e ; w = w ^ ( w << 3 ) add a,a @@ -95,14 +92,6 @@ RAND_LOOP: ld d,l ; y = z ld e,a ; w = t ld (RANDOM_SEED_HIGH),de - push af - djnz RAND_LOOP - pop de - pop af - ld e, a - pop hl - pop af - ld l, a ret ENDP RND: @@ -143,8 +132,8 @@ RND_LOOP: ret ENDP pop namespace -#line 23 "rnd.bas" -#line 1 "/zxbasic/src/arch/zx48k/library-asm/storef.asm" +#line 23 "arch/zx48k/rnd.bas" +#line 1 "/zxbasic/src/lib/arch/zx48k/runtime/storef.asm" push namespace core __PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) push de @@ -172,5 +161,5 @@ __STOREF: ; Stores the given FP number in A EDCB at address HL ld (hl), b ret pop namespace -#line 24 "rnd.bas" +#line 24 "arch/zx48k/rnd.bas" END