Alright, I just got to try this (it turns out the reason it crashed for me was a bug from another program I was testing).

This is simple and practical; good work! It genuinely improves my DCS experience just by having the [.] and [prgm] buttons for renaming and editing. (Especially the [prgm] one as that is quite intuitive, same with [(] and [)] for copy/paste).

You can edit the pages on wikiti btw. As for the mirrored port writing being ignored, that's actually really handy to know. I suspect that two different people contributed those facts, or maybe it was he came person who forgot?

;HL must be non-zero add hl,hl sbc a,a and %00101101 xor l ld l,a ld a,r add a,a ;Because R is a 7-bit register add a,h ;HL is the new seed ;A is the output, or AL for 16 bits.

Spoiler For Explanation:

Upon first inspection, that use of the R register might look like it is being used as a source of randomness, but it is in fact being used as a cheap counter. This leaves us in a very interesting position: If the R register happens to be random or chaotic in your use-case, then that is good! But if R just acts as a counter, then that is also good, because that is what the PRNG needs.

The basic trick is to combine a counter or LCG with an LFSR to smooth out the distribution of the LSFR. Since LSFRs are very fast, and R is a built-in counter on the Z80, we can combine them to make a very, very fast random number generator that is decent quality.

Now, there are some caveats. Due to the nature of the R register, this does not have a fixed cycle length. On average, it has a cycle length of 5592320 (meaning you could expect it to loop after every 5592320 numbers generated). The cycle length could be as low as 65535 (it is essentially just the LFSR), or as high as 8388480. If you wait for external input between calls, then you basically have a true RNG.

Spoiler For Images:

Here is a gif demonstration:

Another good use-case is fire animation! (sorry for the poor quality gif, it's really a lot smoother IRL)

eZ80 8-bit RNG If HL is 24-bit, as in ADL mode on the eZ80, then your LFSR needs different taps (but in this case, it doesn't improve cycle length because we are still using H instead of UHL):

;HL must be non-zero add hl,hl sbc a,a and %10000111 xor l ld l,a ld a,r add a,a ;Because R is a 7-bit register add a,h ;HL is the new seed ;A is the output, or AL for 16 bits.

I have no idea what the speed is on the eZ80. 10 fetches, maybe?

Spoiler For Comparison Images:

this comparison might be a little easier to interpret: (LFSR only)

(combined with R as a counter)

8-bit RNG, 39cc Apparently even an 8-bit LFSR combined with the R register does a great job at generating noise, so here is an even faster version (faster for the Z80, though this code also works on the eZ80):

It has been a long time since I did 68k C and Assembly, but I thought that you could basically "include" a .bmp or .png or what-have-you. I know I can do that with the Z80 calcs and probably eZ80.

If so, I always opt for old-school MS Paint, or mtpaint on Linux.

I have two routines that I am proud of and thought they'd be useful! Binary Search Binary Search is an efficient way to search through sorted data. Regardless of the data, the core of the algorithm is the same, so I made a routine that is the core algorithm! All you have to do is pass a pointer to a routine in IX that compares two pieces of data

;Requires `call_ix` routine that looks like: ; call_ix: ; jp (ix) ; ;IX points to a comparison routine that takes as input: ; HL points to the input element to find ; DE is the element to compare to ;Outputs are: ; carry set if the HL element is less than the DE element ; carry reset if the HL element is greater than or equal to the DE element ; z set if the HL element is equal to the DE element ; nz set if the HL element is not equal to the DE element ; ;This is useful if you have a table of pointers to strings, and want to find a ;string in the array. See the end of this file for an example. ;

binarysearch: ;This is a general-purpose binary search routine. ; ;Inputs: ; BC is the element to find ; HL is the number of elements ; IX points to a callback routine that compares the input element ;Outputs: ; DE is the matching element index ; z means match found ; nz means no match ; In this case, DE is interpreted as where the match should have been ;Destroys: ; AF, DE ;RAM needed: ; 10 bytes of stack space (4 pushes and a call) ; ld de,-1 binarysearch_loop_inc_lower: inc de binarysearch_loop: push hl push de or a sbc hl,de jr z,binarysearch_nomatch rr h rr l add hl,de ld d,h ld e,l push hl ;test index push bc ;input ld h,b ld l,c call call_ix pop bc ;input jr nc,binarysearch_input_bigger_or_equal pop hl ;test index is the new upper index pop de ;restore the lower index pop af ;dummy pop jr binarysearch_loop

binarysearch_input_bigger_or_equal: pop de ;test index +1 is the new lower index pop hl ;dummy pop pop hl ;restore upper index jr nz,binarysearch_loop_inc_lower ;a match was found ;DE is left as the index ret

binarysearch_nomatch: pop de ;lower index pop hl ;upper index (also lower index and test index) or 1 ret

Heapsort Heapsort is a clever and efficient sorting algorithm. Much like the Binary Search routine above, you pass IX pointing to a routine that actually interprets your data, so this can work on even your weirdest data format. IX points to a routine that either swaps two elements, or compares two elements (based on carry flag passed in). NOTE: This also includes the heapify routine, used by heapsort. This might also be useful if you only need to arrange data into a heap structure, but don't need to sort.

; This routine requires the following subroutine: ; call_ix: ; jp (ix) ; ; To use SMC, define SMC. ; #define SMC ; ; If you are not using SMC, you'll need to define `arraylen` to point ;to 2 bytes of scrap RAM

heapsort: ;Inputs: ; BC is the size of the array. ; IX points to the routine that compares or swpas two entries ; HL is the index of the first element ; DE is the index of the second element ; c means swap ; nc means compare HL to DE ; Should return: ; z if they are equal ; nc if HL>=DE ; c if HL<DE ;Outputs: ; The data is sorted. ;Destroys: ; All ;Notes: ; You can make the comparison routine work any way that you want :) ; For example, you can invert the carry flag output to sort descending.

;If the array is size 0 or 1, then it is sorted inc b dec b jr nz,heapsort_heapify dec c ret z inc c ret z

heapsort_heapify: call heapify ld hl,(arraylen) heapsort_loop: dec hl ld (arraylen),hl push hl ;HL is the last element ld de,0 call heapsort_swap ld bc,1 call propogate pop hl ld a,h or l jr nz,heapsort_loop ret

heapify: ;Inputs: ; HL points to the array data ; BC is the size of the array. NOT GREATER THAN 32767 ; IX points to the routine that compares the values ld (arraylen),bc srl b rr c _: push bc call propogate pop bc dec bc ld a,b or c jr nz,-_ ret

propogate: ;BC-1 is the parent index ;2BC-1 is the child0 index ;2BC is the child1 index sla c rl b ld d,b ld e,c

sbc hl,de add hl,de ret c ;no children ;z means one child ;compare the two children ld h,b ld l,c dec hl ;HL is the child0 index ;DE is the child1 index call nz,heapsort_cmp jr nc,+_ ex de,hl _:

;parent is (HL+1)>>1 ;child is HL ld d,h ld e,l inc hl srl h rr l dec hl call heapsort_cmp ret nc call heapsort_swap

;values heapsort_swapped, now set parent=child+1 ld b,d ld c,e inc bc jr propogate

heapsort_swap: ;HL and DE are the indices of the elements to heapsort_swap push hl push de scf call call_ix pop de pop hl ret

heapsort_cmp: push hl push de or a call call_ix pop de pop hl ret