Files
open-roms/src/basic/engine_variables/array_create.s
T

247 lines
4.3 KiB
ArmAsm

// #LAYOUT# STD * #TAKE
// #LAYOUT# * BASIC_0 #TAKE
// #LAYOUT# * * #IGNORE
array_create:
// First retrieve array name
jsr fetch_variable_name
bcs_16 do_SYNTAX_error
// XXX check if the array already exists
// Push variable name and FOUR6 on the stack - fetching dimensions might cause
// the to be overwritten by the expression parser
lda VARNAM+0
pha
lda VARNAM+1
pha
lda FOUR6
pha
// Check if the array dimension is given - if not, assume '10' was specified
bit DIMFLG
bmi array_create_fetch_dims
lda #$0A
pha
lda #$00
pha
ldx #$01
bne array_create_store_dims // branch always
array_create_fetch_dims:
ldx #$00 // counts number of dimensions
// FALLTROUGH
array_create_fetch_dims_loop:
inx
// Check if the stack has reasonable space free
jsr check_stack_space
// Fetch the dimension, increment it by 1, and put it on the stack;
// confirmed with original ROM, that it also stores dimensions in the reverse order
jsr fetch_uint16
bcs_16 do_SYNTAX_error
#if !HAS_OPCODES_65CE02
inc LINNUM+0
bne !+
inc LINNUM+1
!:
#else
inw LINNUM
#endif
beq_16 do_OUT_OF_MEMORY_error
lda LINNUM+0
pha
lda LINNUM+1
pha
// Check if more dimensions are given
jsr fetch_character_skip_spaces
cmp #$2C // ','
beq array_create_fetch_dims_loop
cmp #$29 // ')'
bne_16 do_SYNTAX_error
// FALLTROUGH
array_create_store_dims:
// We got the dimensions, time to alocate memory. Arrays are not declared too often,
// it will be easier if we perform the garbage collection now
phx_trash_a
jsr varstr_garbage_collect
// __FAC1+1/+2 will be used to calculate number of elements
ldy #$01
sty __FAC1+1
dey
sty __FAC1+2
// Check if there is enough free memory for the header
pla // .A - number of dimensions
sta __FAC1+0
jsr helper_array_create_checkmem
lda __FAC1+0
// Create the initial array structure (header) - format checked by creating arrays with original ROM
// Bytes 0/1 - array name, but we can not fetch it easily now, so skip it for now
// Bytes 2/3 - offset to the next array, skip it for now too
// Byte 4 - number of dimensions
// Bytes 5+ - max index in each dimension (big endian!), this will be set in a loop
ldy #$04
#if CONFIG_MEMORY_MODEL_60K
stx INDEX+2
ldx #<STREND
jsr poke_under_roms
ldx INDEX+2
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
sta (STREND), y
#endif
iny // .Y - index to store dimension sizes
tax // .X - dimensions not stored yet
// FALLTROUGH
array_create_store_loop:
#if CONFIG_MEMORY_MODEL_60K
stx INDEX+2
ldx #<STREND
pla
jsr poke_under_roms
sta __FAC1+4
iny
pla
jsr poke_under_roms
sta __FAC1+3
iny
ldx INDEX+2
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
pla
sta (STREND), y
sta __FAC1+4
iny
pla
sta (STREND), y
sta __FAC1+3
iny
#endif
jsr helper_array_create_mul
dex
bne array_create_store_loop
// FALLTROUGH
array_create_store_dims_done:
// Restore FOUR6, calculate number of bytes needed for storage
pha
sta FOUR6 // XXX do we need to store this value in FOUR6? is it still needed?
sta __FAC1+3
stx __FAC1+4 // .X is 0 at this point
jsr helper_array_create_mul
// Check if there is enough free memory
jsr helper_array_create_checkmem
// Retrieve and store array name
ldy #$00
#if CONFIG_MEMORY_MODEL_60K
ldx #<STREND
pla
jsr poke_under_roms
iny
pla
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
pla
sta (STREND), y
iny
pla
sta (STREND), y
#endif
// Calculate and store offset to the next array
lda #$02
jsr helper_INDEX_up_A
lda __FAC1+0
asl
jsr helper_INDEX_up_A
#if CONFIG_MEMORY_MODEL_60K
// .X already contains STREND
ldy #$02
lda INDEX+0
jsr poke_under_roms
iny
lda INDEX+1
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
ldy #$02
lda INDEX+0
sta (STREND), y
iny
lda INDEX+1
sta (STREND), y
#endif
// Clear newly alocated area, adjust STREND
// XXX implement this
jmp do_NOT_IMPLEMENTED_error