1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-18 00:29:30 +00:00

Library improvements:

– random module
– ensure_mixedcase() function
This commit is contained in:
Karol Stasiak 2018-12-30 18:59:32 +01:00
parent fc56c11b31
commit 75e572f58c
9 changed files with 158 additions and 54 deletions

View File

@ -39,7 +39,13 @@
* [`stdlib` module](stdlib/stdlib.md)
* [Other cross-platform modules](stdlib/other.md)
* [`string` module](stdlib/string.md)
* [Modules for reading input devices](stdlib/input.md)
* [Other cross-platform modules (`err`, `stdio`, `random`)](stdlib/other.md)
* [Definitions available on only some platforms](stdlib/frequent.md)
* [C64-only modules](stdlib/c64.md)

View File

@ -43,7 +43,7 @@
* [Modules for reading input devices](stdlib/input.md)
* [Other cross-platform modules (`err`, `stdio`)](stdlib/other.md)
* [Other cross-platform modules (`err`, `stdio`, `random`)](stdlib/other.md)
* [Definitions available on only some platforms](stdlib/frequent.md)

View File

@ -14,6 +14,10 @@ Prints a string of length `len` located at address `str`.
Prints a null-terminated string located at address `str`.
If the string is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `void ensure_mixedcase()`
On targets that have separate all-caps and mixed-case modes (like most Commodore machines), switches to the mixed-case mode.
## err
@ -24,3 +28,29 @@ Standard error codes. All codes other than `err_ok` suggest that the last operat
#### `error_number errno`
The result of the last operation.
## random
A simple and reasonably fast random number generator. Not suitable for cryptographic or simulation uses.
#### `word rand_seed`
Random number generator state.
#### `byte rand()`
Get a random byte (0255) and update the state of the generator.
#### `void init_rand_seed()`
Initializes the random number generator state.
This may take a long time, even several frames, depending on the target.
Current implementation:
* On C64, spends two frames reading noise data from the SID chip.
* On Z80, reads the refresh register.
* On all other targets, sets the seed to 1.

View File

@ -1,4 +1,6 @@
import random
array reverse_palette[256] align(256)
#if CBM
@ -119,53 +121,3 @@ void fire() {
p += COLUMN_COUNT
}
}
word rand_seed
#if CPU_6502
asm byte rand() {
ldx #8
lda rand_seed+0
__rand_loop:
asl
rol rand_seed+1
bcc __no_eor
eor #$2D
__no_eor:
dex
bne __rand_loop
sta rand_seed+0
? rts
}
#elseif CPU_Z80
inline asm byte rand() {
ld b,8
ld hl,(rand_seed)
__rand_loop:
add hl,hl
jp nc, __no_eor
ld a,l
xor $2D
ld l,a
__no_eor:
djnz __rand_loop
ld (rand_seed),hl
? ret
}
#endif
#if CBM_64
inline void init_rand_seed() {
poke($D40E, $ff)
poke($D40F, $ff)
poke($D412, $80)
while vic_raster != $70 {}
rand_seed.hi = peek($D41B)
while vic_raster != $40 {}
rand_seed.lo = peek($D41B)
}
#else
inline void init_rand_seed() {
rand_seed = 1
}
#endif

View File

@ -3,9 +3,10 @@
import stdio
array hello_world = "hello world"
array hello_world = "Hello world"
void main() {
ensure_mixedcase()
#if CBM_64 || CBM_264
set_bg_color(green)
@ -16,7 +17,7 @@ void main() {
putstr(hello_world, hello_world.length)
new_line()
putstrz("hello world again"z)
putstrz("Hello world again"z)
#if not(CPM)
while(true){}

10
include/random.mfk Normal file
View File

@ -0,0 +1,10 @@
word rand_seed
#if ARCH_6502
import random_6502
#elseif ARCH_I80
import random_i80
#else
#warn Unsupported architecture
#endif

43
include/random_6502.mfk Normal file
View File

@ -0,0 +1,43 @@
import random
#if not(ARCH_6502)
#warn random_6502 module should be only used on 6502-compatible targets
#endif
asm byte rand() {
? ldx #8
? lda rand_seed+0
__rand_loop:
asl
? rol rand_seed+1
bcc __no_eor
eor #$2D
__no_eor:
dex
bne __rand_loop
? sta rand_seed+0
? rts
}
#if CBM_64
void init_rand_seed() {
poke($D40E, $ff)
poke($D40F, $ff)
poke($D412, $80)
while vic_raster != $70 {}
rand_seed.hi = peek($D41B)
while vic_raster != $40 {}
rand_seed.lo = peek($D41B)
}
#else
inline void init_rand_seed() {
// TODO: find a better source of randomness
rand_seed = 1
}
#endif

47
include/random_i80.mfk Normal file
View File

@ -0,0 +1,47 @@
import random
#if not(ARCH_I80)
#warn stdlib_i80 module should be only used on Intel 8080-like targets
#endif
#pragma zilog_syntax
asm byte rand() {
ld b,8
ld hl,(rand_seed)
__rand_loop:
add hl,hl
? jp nc, __no_eor
ld a,l
xor $2D
ld l,a
__no_eor:
#if CPUFEATURE_Z80
djnz __rand_loop
#else
dec b
? jp nz, __rand_loop
#endif
ld (rand_seed),hl
? ret
}
#if CPUFEATURE_Z80
inline asm void init_rand_seed() {
ld a,r
ld (rand_seed), a
ld a,r
ld (rand_seed+1), a
? ret
}
#else
inline void init_rand_seed() {
// TODO: find a better source of randomness
rand_seed = 1
}
#endif

View File

@ -59,3 +59,18 @@ void putword(word w) {
putchar('0')
}
}
#if CBM_PET
inline asm void ensure_mixedcase() {
? lda #14
! sta 59468
? rts
}
#elseif CBM
inline void ensure_mixedcase() {
putchar(14)
}
#else
inline void ensure_mixedcase() {
}
#endif