He estado dedicando unos días a hacer ese COREUPGR, y en realidad lo tengo programado completo, pero no lo voy a terminar. La razón es que no encuentro un entorno de debug adecuado para hacerlo, y me parece una herramienta suficientemente delicada como para hacer un debug muy concienzudo, para el que no vale hacer ñapas a la antigua usanza en plan escribir cosas en pantalla, o cambiar el color de tal caracter, tiene que ser algo más serio.
Es posible que en el futuro, cuando haya un emulador que me permita hacer eso pueda plantearmelo, pero como ese futuro no se si será cercano o lejano, voy a dejar aquí el código, advirtiendo previamente que:
1) Seguro que tiene bugs, si alguien lo retoma, que no lo de por bueno, no he podido hacer debug del mismo.
2) Seguramente es optimizable en tiempo y espacio. No es un asunto que me haya preocupado porque siendo uno de mis primeros programas en ensamblador de Z80 serios, lo que más me preocupaba era la legibilidad.
3) Se compila con sjasmplus (sjasmplus coreupgr.asm), y parte de una mezcla del ROMSUPGR y el UPGRADE de Antonio Villena.
Código: Seleccionar todo
; (C) 2016 Uto - some parts are (C) Antonio Villena
; LICENSE: CC BY-SA
; TO BE COMPILED WITH SJASMPLUS
output COREUPGR
macro wreg dir, value
call rst28
defb dir, value
endm
; ** ZX-UNO PORTS **
define ZXUNO_PORT $FC3B
define MASTERCONF 0
define FLASHSPI 2
define FLASHCS 3
define SCANDBLCTRL 11
; ** ESXDOS VARS **
define FA_READ $01
define M_GETSETDRV $89
define F_OPEN $9A
define F_CLOSE $9B
define F_READ $9D
define F_FSTAT $A1
org $2000 ; ESXDOS dot command org
; ** CHECK ROOTED ROM **
Main ; ld bc, ZXUNO_PORT
; out (c), MASTERCONF
; inc b
; in f, (c)
; jp p, Nonlock
; call Print
; dz 'ROM not rooted'
; ret
; ** CHECK IF PARAMS AVALIABLE **
Nonlock ld a, h
or l
jp z, Syntax ; No params, show Syntax
; ** PARSE PARAM1 **
ld a,(hl)
cp '2' ; less than 2
jp c, Syntax
cp ':' ; plus than 9 (colon is ASCII char after '9')
jp nc, Syntax
sub 48
ld (coreSlot+1), a ; modify code so core slot number is used later
; ** CHECK THERE IS A SPACE **
inc hl
ld a,(hl)
cp ' '
jp nz, Syntax
; ** PARSE PARAM2 **
ld bc, 0 ; Will count filename length
fileNameLoop inc hl
ld a, (hl) ; Copying second parameter to Filename Variable
cp 13
jr z, fileNameEnd ; Found a zero, filename finished
cp 32
jp z, Syntax ; Found a space, no more parameters allowed, show Syntax
ld (de), a
cp '.'
jr nz, filenameNoDot
ld (dotFound), a ; Make dotFound be non zero
filenameNoDot inc de
jr fileNameLoop
; ** ADD ZX1 EXTENSION IF NO EXTENSION **
fileNameEnd ld a, (dotFound) ; Check if file name had a dot
or a
jr nz, fileNameEnd2
ld hl, zx1Extension ; Otherwise, add .ZX1 extension to file name
ld b, 4
ldir
; ** GET FILE NAME LENGTH AT BC **
fileNameEnd2 ld hl, de
ld bc, FileName + 1 ; +1 as de already points to next position after last character
sub hl, bc
ld bc, hl
xor a
ld (de), a ; Add ASCIIZ zero mark
; ** CHECK FILENAME NO LONGER THAN 32 CHARS **
ld a, b
or a
jp nz, Syntax ; 256 or more characters!
ld a, c
cp 32
jp nc, Syntax ; more than 32 characters
ld a, 32
sub c ; get how many spaces will be needed to fill up to 32 chars
ld (fillSpaces+1), a ; modify code below so later the name is filled up to 32 bytes with spaces
; ** SET TURBO MODE 28 MHz FOR FASTER UPDATE **
ld a, SCANDBLCTRL ;
dec b
out (c), a
inc b
in a, (c)
ld (TurboValue+1), a ; Store current turbo value so speed is brought back to previous value on exit
or $c0
out (c), a
; ** CHECK SD CARD READY **
xor a ; A=0 (current unit)
rst $08
db M_GETSETDRV
ret c
; ** OPEN FILE **
ld b, FA_READ
ld hl, FileName ; HL = Pointer to ASCIIZ filename
rst $08
db F_OPEN
jr nc, FileFound
ld hl, FileFolder ; If file not found, try again in /CORES folder
rst $08
db F_OPEN
ret c
; ** GET CODE READY FOR READING FILE **
FileFound ld (handle+1), a ; Modifies code so "ld a, 0" at (handle) becomes "ld a, <handle>"
;** CHECK CORE SIZE **
CheckSize rst $08
db F_FSTAT ; Size must be ($00054000 / 344,064 bytes)
ret c
ld hl, FileName+7
ld a,(hl)
or a
jp nz, SizeError
inc hl
ld a,(hl)
cp $40
jp nz, SizeError
inc hl
ld a,(hl)
cp $05
jp nz, SizeError
inc hl
ld a,(hl)
or a
jp z, Start
SizeError call Print
db 'Core file must be 344,064 bytes long', 13
ret
; ** WRITE START MESSAGE **
Start call Print
dz 'Upgrading CORE from SD', 13
; ** CALCULATE CORE POSITION IN FLASH **
exx
ld hl, $0040 ; position of CORE 1 in flash minus $540 (core 1 is at $580[00])
ld de, $0540
coreSlot ld a, 0 ; this code is modified above so it actually will be ld a, <core slot number>
ld b,a
flashPtrLoop add hl, de
djnz flashPtrLoop
ld de, hl
exx
; ** WRITE CORE **
MainWriteLoop ld hl, $8000
ld bc, $4000
handle ld a, 0 ; This code is modified above si actually will be ld a, <handle> when executed
rst $08
db F_READ ; Read 16K at $8000
jp c, ReadError
; ** CHECK EOF **
ld a, b
or c
jp z, WriteFinished ; Exit if 0 bytes read (EOF)
; ** WRITE 16K TO SPI FLASH **
ld a, 64 ; write 64 pages of 256 bytes (16K)
ld hl, $8000 ; located at $8000
exx
call writeFlash
inc de
exx
; ** WRITE DOTS AS PROGRESS MARK**
ld a, '.'
exx
push de
rst $10
pop de
exx
jp MainWriteLoop
; ** CLOSE FILE **
WriteFinished ld a, (handle+1) ; Take handle value from preceding code
rst $08
db F_CLOSE
;** READ CORE NAMES FROM FLASH **
readCoreNames ld de, $8000 ; Core names are located at $007100, 32 bytes per core, 8 core names (2 to 9), 256 total bytes
ld hl, $0071
ld a,1
call readFlash
;** MAKE HL POINT TO REQUESTED CORE NAME **
ld a, (coreSlot+1) ; get core slot number from code aboves
dec a ; Decrements 1 cause core 1 ==> 0 offset, core 2 => $20 offset, etc.
ld de, $0071
ld h, 0
ld l, a
add hl, hl
add hl, hl
add hl, hl
add hl, hl ; HL = A * 32
add hl, de ; HL = A * 32 + $0071
;** UPDATE CORE NAME IN MEMORY **
updateCoreName ld de, FileName
coreNameLoop ld a, (de)
or a
jr z, fillSpaces
ld (hl), a
inc hl
jr coreNameLoop
;** FILL WITH SPACES UP TO 32 BYTES **
fillSpaces ld b, 0 ; That 0 is replaced by numer of spaces above (self-modified code)
ld a, $20
fillSpLoop ld (hl), a
inc hl
djnz fillSpLoop
; ** SAVE CORE NAMES TO FLASH **
saveCoreNames ld de, $8000
ld hl, $0071
ld a,1
call writeFlash
; ** RESTORE PREVIOUS TURBO MODE **
ld bc, ZXUNO_PORT
ld a, SCANDBLCTRL
out (c), a
inc b
TurboValue ld a, 0
out (c), a
; ** WRITE SUCCESS MESSAGE AND EXIT **
call Print
dz 13, 'Core upgraded sucessfully', 13
ret
ReadError call Print
dz 13,'Unexpected error while reading the file',13
ret
Syntax call Print
db 'Syntax:',13,13
db '.COREUPGR <core slot> <file>', 13, 13
db '<core slot> : 2-9', 13
dz '<filename> : max 32 bytes long', 13
ret
;***********************************************************************************
; AUX FUNCTIONS *
;***********************************************************************************
; -----------------------------------
; Print ASCIIZ String
; Parameters:
; None, just DB with ASCIIZ string
; after the "call Print"
; -----------------------------------
Print pop hl
db $3e
Print1 rst $10
ld a, (hl)
inc hl
or a
jr nz, Print1
jp (hl)
; ------------------------------------------
; Read from SPI flash
; Parameters:
; DE: destination address
; HL: source address without last byte
; A: number of pages (256 bytes) to read
; ------------------------------------------
readFlash ex af, af'
xor a
push hl
wreg FLASHCS, 0 ; activamos spi, enviando un 0
wreg FLASHSPI, 3 ; envio FLASHSPI un 3, orden de lectura
pop hl
push hl
out (c), h
out (c), l
out (c), a
ex af, af'
ex de, hl
in f, (c)
rdfls1 ld e, $20
rdfls2 ini
inc b
ini
inc b
ini
inc b
ini
inc b
ini
inc b
ini
inc b
ini
inc b
ini
inc b
dec e
jr nz, rdfls2
dec a
jr nz, rdfls1
wreg FLASHCS, 1
pop hl
ret
; ------------------------
; Write to SPI flash
; Parameters:
; A: number of pages (256 bytes) to write
; DE: target address without last byte ($xxxx00)
; HL': source address from memory
; ------------------------
writeFlash ex af, af'
xor a
wrfls1 wreg FLASHCS, 0 ; disable spi, sending 0
wreg FLASHSPI, 6 ; send write enable
wreg FLASHCS, 1 ; deactivate spi, send 1
wreg FLASHCS, 0 ; activate spi, send 0
wreg FLASHSPI, $20 ; send erase sector
out (c), d
out (c), e
out (c), a
wreg FLASHCS, 1 ; deactivate spi, send 1
wrfls2 call waits5
wreg FLASHCS, 0 ; activate spi, send 0
wreg FLASHSPI, 6 ; send write enable
wreg FLASHCS, 1 ; deactivate spi, send 1
wreg FLASHCS, 0 ; activate spi, send 0
wreg FLASHSPI, 2 ; page program
out (c), d
out (c), e
out (c), a
ld a, $20
exx
ld bc, ZXUNO_PORT+$100
wrfls3 inc b
outi
inc b
outi
inc b
outi
inc b
outi
inc b
outi
inc b
outi
inc b
outi
inc b
outi
dec a
jr nz, wrfls3
exx
wreg FLASHCS, 1 ; deactivate spi, send 1
ex af, af'
dec a
jr z, waits5
ex af, af'
inc e
ld a, e
and $0f
jr nz, wrfls2
ld hl, wrfls1
push hl
waits5 wreg FLASHCS, 0 ; activate spi, send 0
wreg FLASHSPI, 5 ; send read status
in a, (c)
waits6 in a, (c)
and 1
jr nz, waits6
wreg FLASHCS, 1 ; deactivate spi, send 1
ret
rst28 ld bc, ZXUNO_PORT + $100
pop hl
outi
ld b, (ZXUNO_PORT >> 8)+2
outi
jp (hl)
;*******************************************************************************
; VARIABLES *
;*******************************************************************************
zx1Extension db '.ZX1'
dotFound db 0 ; wether the core file name parameter contained a dot or not
FileFolder db '/CORES/'
FileName db 0