mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
reverse() added (byte+word)
This commit is contained in:
parent
d837cc11f9
commit
1cc1f2d91d
@ -26,7 +26,7 @@ which aims to provide many conveniences over raw assembly code (even when using
|
||||
- abstracting away low level aspects such as ZeroPage handling, program startup, explicit memory addresses
|
||||
- various code optimizations (code structure, logical and numerical expressions, unused code removal...)
|
||||
- inline assembly allows you to have full control when every cycle or byte matters
|
||||
- many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``memset``, ``memcopy``
|
||||
- many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``memset``, ``memcopy``, ``sort`` and ``reverse``
|
||||
|
||||
Rapid edit-compile-run-debug cycle:
|
||||
|
||||
|
@ -1535,14 +1535,15 @@ _sort_loop ldy c64.SCRATCH_ZPB1 ;start of subroutine sort
|
||||
_l1 dey
|
||||
dey
|
||||
beq _l3
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
cmp c64.SCRATCH_ZPWORD2
|
||||
iny
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
dey
|
||||
cmp c64.SCRATCH_ZPWORD2+1
|
||||
bne +
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
cmp c64.SCRATCH_ZPWORD2
|
||||
+ bmi _l1
|
||||
sbc c64.SCRATCH_ZPWORD2+1
|
||||
bvc +
|
||||
eor #$80
|
||||
+ bmi _l1
|
||||
_l2 sty _work1 ;index of potentially largest value
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
sta c64.SCRATCH_ZPWORD2 ;potentially largest value
|
||||
@ -1571,3 +1572,102 @@ _l3 ldy c64.SCRATCH_ZPB1 ;where the largest value shall be put
|
||||
_work1 .byte 0
|
||||
_work3 .word 0
|
||||
.pend
|
||||
|
||||
|
||||
reverse_b .proc
|
||||
; --- reverse an array of bytes (in-place)
|
||||
; inputs: pointer to array in c64.SCRATCH_ZPWORD1, length in A
|
||||
_left_index = c64.SCRATCH_ZPWORD2
|
||||
_right_index = c64.SCRATCH_ZPWORD2+1
|
||||
pha
|
||||
sec
|
||||
sbc #1
|
||||
sta _left_index
|
||||
lda #0
|
||||
sta _right_index
|
||||
pla
|
||||
lsr a
|
||||
tay
|
||||
_loop sty c64.SCRATCH_ZPREG
|
||||
ldy _left_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
pha
|
||||
ldy _right_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
ldy _left_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
pla
|
||||
ldy _right_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
inc _right_index
|
||||
dec _left_index
|
||||
ldy c64.SCRATCH_ZPREG
|
||||
dey
|
||||
bne _loop
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
reverse_w .proc
|
||||
; --- reverse an array of words (in-place)
|
||||
; inputs: pointer to array in c64.SCRATCH_ZPWORD1, length in A
|
||||
_left_index = c64.SCRATCH_ZPWORD2
|
||||
_right_index = c64.SCRATCH_ZPWORD2+1
|
||||
pha
|
||||
asl a ; *2 because words
|
||||
sec
|
||||
sbc #2
|
||||
sta _left_index
|
||||
lda #0
|
||||
sta _right_index
|
||||
pla
|
||||
lsr a
|
||||
pha
|
||||
tay
|
||||
; first reverse the lsbs
|
||||
_loop_lo sty c64.SCRATCH_ZPREG
|
||||
ldy _left_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
pha
|
||||
ldy _right_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
ldy _left_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
pla
|
||||
ldy _right_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
inc _right_index
|
||||
inc _right_index
|
||||
dec _left_index
|
||||
dec _left_index
|
||||
ldy c64.SCRATCH_ZPREG
|
||||
dey
|
||||
bne _loop_lo
|
||||
; now reverse the msbs
|
||||
dec _right_index
|
||||
inc _left_index
|
||||
inc _left_index
|
||||
inc _left_index
|
||||
pla
|
||||
tay
|
||||
_loop_hi sty c64.SCRATCH_ZPREG
|
||||
ldy _left_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
pha
|
||||
ldy _right_index
|
||||
lda (c64.SCRATCH_ZPWORD1),y
|
||||
ldy _left_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
pla
|
||||
ldy _right_index
|
||||
sta (c64.SCRATCH_ZPWORD1),y
|
||||
dec _right_index
|
||||
dec _right_index
|
||||
inc _left_index
|
||||
inc _left_index
|
||||
ldy c64.SCRATCH_ZPREG
|
||||
dey
|
||||
bne _loop_hi
|
||||
|
||||
rts
|
||||
.pend
|
||||
|
@ -832,7 +832,7 @@ internal class AstChecker(private val program: Program,
|
||||
printWarning("result values of subroutine call are discarded", functionCallStatement.position)
|
||||
}
|
||||
|
||||
if(functionCallStatement.target.nameInSource.last() in setOf("lsl", "lsr", "rol", "ror", "rol2", "ror2", "swap", "sort")) {
|
||||
if(functionCallStatement.target.nameInSource.last() in setOf("lsl", "lsr", "rol", "ror", "rol2", "ror2", "swap", "sort", "reverse")) {
|
||||
// in-place modification, can't be done on literals
|
||||
if(functionCallStatement.arglist.any { it !is IdentifierReference && it !is RegisterExpr && it !is ArrayIndexedExpression && it !is DirectMemoryRead }) {
|
||||
checkResult.add(ExpressionError("can't use that as argument to a in-place modifying function", functionCallStatement.position))
|
||||
|
@ -336,6 +336,38 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
||||
else
|
||||
throw AssemblyError("weird type")
|
||||
}
|
||||
"reverse" -> {
|
||||
val variable = fcall.arglist.single()
|
||||
if (variable is IdentifierReference) {
|
||||
val decl = variable.targetVarDecl(program.namespace)!!
|
||||
val varName = asmgen.asmIdentifierName(variable)
|
||||
val numElements = decl.arraysize!!.size()
|
||||
when (decl.datatype) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
asmgen.out("""
|
||||
lda #<$varName
|
||||
ldy #>$varName
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
sty ${C64Zeropage.SCRATCH_W1 + 1}
|
||||
lda #$numElements
|
||||
jsr prog8_lib.reverse_b
|
||||
""")
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
asmgen.out("""
|
||||
lda #<$varName
|
||||
ldy #>$varName
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
sty ${C64Zeropage.SCRATCH_W1 + 1}
|
||||
lda #$numElements
|
||||
jsr prog8_lib.reverse_w
|
||||
""")
|
||||
}
|
||||
DataType.ARRAY_F -> TODO("reverse floats (consider another solution if possible - this will be quite slow, if ever implemented)")
|
||||
else -> throw AssemblyError("weird type")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
translateFunctionArguments(fcall.arglist, func)
|
||||
asmgen.out(" jsr prog8_lib.func_$functionName")
|
||||
|
@ -28,6 +28,7 @@ val BuiltinFunctions = mapOf(
|
||||
"lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null),
|
||||
"lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null),
|
||||
"sort" to FunctionSignature(false, listOf(BuiltinFunctionParam("array", ArrayDatatypes)), null),
|
||||
"reverse" to FunctionSignature(false, listOf(BuiltinFunctionParam("array", ArrayDatatypes)), null),
|
||||
// these few have a return value depending on the argument(s):
|
||||
"max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMax) }, // type depends on args
|
||||
"min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinMin) }, // type depends on args
|
||||
|
@ -158,7 +158,7 @@ Design principles and features
|
||||
- The compiler tries to optimize the program and generated code, but hand-tuning of the
|
||||
performance or space-critical parts will likely still be required. This is supported by
|
||||
the ability to easily write embedded assembly code directly in the program source code.
|
||||
- There are many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``memset``, ``memcopy``
|
||||
- There are many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``memset``, ``memcopy``, ``sort`` and ``reverse``
|
||||
|
||||
|
||||
.. _requirements:
|
||||
|
@ -663,52 +663,58 @@ cos16u(x)
|
||||
Fast 16-bit uword cosine of angle 0..255, result is in range 0..65535
|
||||
|
||||
cos16(x)
|
||||
Fast 16-bit word cosine of angle 0..255, result is in range -32767..32767
|
||||
Fast 16-bit word cosine of angle 0..255, result is in range -32767..32767
|
||||
|
||||
abs(x)
|
||||
Absolute value.
|
||||
Absolute value.
|
||||
|
||||
tan(x)
|
||||
Tangent.
|
||||
Tangent.
|
||||
|
||||
atan(x)
|
||||
Arctangent.
|
||||
Arctangent.
|
||||
|
||||
ln(x)
|
||||
Natural logarithm (base e).
|
||||
Natural logarithm (base e).
|
||||
|
||||
log2(x)
|
||||
Base 2 logarithm.
|
||||
|
||||
sqrt16(w)
|
||||
16 bit unsigned integer Square root. Result is unsigned byte.
|
||||
16 bit unsigned integer Square root. Result is unsigned byte.
|
||||
|
||||
sqrt(x)
|
||||
Floating point Square root.
|
||||
Floating point Square root.
|
||||
|
||||
round(x)
|
||||
Rounds the floating point to the closest integer.
|
||||
Rounds the floating point to the closest integer.
|
||||
|
||||
floor (x)
|
||||
Rounds the floating point down to an integer towards minus infinity.
|
||||
Rounds the floating point down to an integer towards minus infinity.
|
||||
|
||||
ceil(x)
|
||||
Rounds the floating point up to an integer towards positive infinity.
|
||||
Rounds the floating point up to an integer towards positive infinity.
|
||||
|
||||
rad(x)
|
||||
Degrees to radians.
|
||||
Degrees to radians.
|
||||
|
||||
deg(x)
|
||||
Radians to degrees.
|
||||
Radians to degrees.
|
||||
|
||||
max(x)
|
||||
Maximum of the values in the array value x
|
||||
Maximum of the values in the array value x
|
||||
|
||||
min(x)
|
||||
Minimum of the values in the array value x
|
||||
Minimum of the values in the array value x
|
||||
|
||||
sum(x)
|
||||
Sum of the values in the array value x
|
||||
Sum of the values in the array value x
|
||||
|
||||
sort(array)
|
||||
Sort the array in ascending order (in-place)
|
||||
|
||||
reverse(array)
|
||||
Reverse the values in the array (in-place). Can be used after sort() to sort an array in descending order.
|
||||
|
||||
len(x)
|
||||
Number of values in the array value x, or the number of characters in a string (excluding the size or 0-byte).
|
||||
|
@ -135,18 +135,16 @@ main {
|
||||
|
||||
; first sort vertices to sprite order so the back/front order is correct as well
|
||||
; (simple bubble sort as it's only 8 items to sort)
|
||||
; TODO make a builtin function sort()
|
||||
sort(rotatedz)
|
||||
; for ubyte sorti in 6 to 0 step -1 {
|
||||
; for ubyte i1 in 0 to sorti {
|
||||
; ubyte i2 = i1+1
|
||||
; if(rotatedz[i1] > rotatedz[i2]) {
|
||||
; swap(rotatedx[i1], rotatedx[i2])
|
||||
; swap(rotatedy[i1], rotatedy[i2])
|
||||
; swap(rotatedz[i1], rotatedz[i2])
|
||||
; }
|
||||
; }
|
||||
; }
|
||||
for ubyte sorti in 6 to 0 step -1 {
|
||||
for ubyte i1 in 0 to sorti {
|
||||
ubyte i2 = i1+1
|
||||
if(rotatedz[i1] > rotatedz[i2]) {
|
||||
swap(rotatedx[i1], rotatedx[i2])
|
||||
swap(rotatedy[i1], rotatedy[i2])
|
||||
swap(rotatedz[i1], rotatedz[i2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ubyte[] spritecolors = [1,1,7,15,12,11,9,9]
|
||||
|
||||
|
62
examples/sorting.p8
Normal file
62
examples/sorting.p8
Normal file
@ -0,0 +1,62 @@
|
||||
%import c64lib
|
||||
%import c64utils
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
|
||||
ubyte[] uba = [10,0,2,8,5,4,3,9]
|
||||
uword[] uwa = [1000,0,200,8000,50,40000,3,900]
|
||||
byte[] ba = [-10,0,-2,8,5,4,-3,9,-99]
|
||||
word[] wa = [-1000,0,-200,8000,50,31111,3,-900]
|
||||
|
||||
c64scr.print("original\n")
|
||||
print_arrays()
|
||||
|
||||
sort(uba)
|
||||
sort(uwa)
|
||||
sort(ba)
|
||||
sort(wa)
|
||||
|
||||
c64scr.print("sorted\n")
|
||||
print_arrays()
|
||||
|
||||
reverse(uba)
|
||||
reverse(uwa)
|
||||
reverse(ba)
|
||||
reverse(wa)
|
||||
|
||||
c64scr.print("reversed\n")
|
||||
print_arrays()
|
||||
return
|
||||
|
||||
|
||||
sub print_arrays() {
|
||||
for ubyte ub in uba {
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for uword uw in uwa {
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for byte bb in ba {
|
||||
c64scr.print_b(bb)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for word ww in wa {
|
||||
c64scr.print_w(ww)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
%import c64lib
|
||||
%import c64utils
|
||||
%import c64flt
|
||||
%zeropage dontuse
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
|
||||
@ -9,9 +8,8 @@ main {
|
||||
|
||||
ubyte[] uba = [10,0,2,8,5,4,3,9]
|
||||
uword[] uwa = [1000,0,200,8000,50,40000,3,900]
|
||||
byte[] ba = [-10,0,-2,8,5,4,-3,9]
|
||||
byte[] ba = [-10,0,-2,8,5,4,-3,9,-99]
|
||||
word[] wa = [-1000,0,-200,8000,50,31111,3,-900]
|
||||
float[] fla = [-2.2, 1.1, 3.3, 0.0]
|
||||
|
||||
for ubyte ub in uba {
|
||||
c64scr.print_ub(ub)
|
||||
@ -66,11 +64,41 @@ main {
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
reverse(uba)
|
||||
reverse(uwa)
|
||||
reverse(ba)
|
||||
reverse(wa)
|
||||
|
||||
for ubyte ub3 in uba {
|
||||
c64scr.print_ub(ub3)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for uword uw3 in uwa {
|
||||
c64scr.print_uw(uw3)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for byte bb3 in ba {
|
||||
c64scr.print_b(bb3)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for word ww3 in wa {
|
||||
c64scr.print_w(ww3)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
ubyte qq=X
|
||||
c64scr.print_ub(qq)
|
||||
|
||||
; TODO 2 for loops that both define the same loopvar -> double definition -> fix second for -> 'unknown symbol' ????
|
||||
; TODO code runs into a subroutine that follows it instead of inserting an implicit return
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user