Reading and writing data to disk in FDS
Moderator: Moderators
-
- Posts: 4
- Joined: Sun Sep 29, 2024 6:40 am
Reading and writing data to disk in FDS
Hi there.
I'm developing my original FDS game with original 3D printed disk. (https://x.com/HSA_Entmt/status/1829779467293900948)
My work is almost completed. But I couldn't implement save high score.
Does anyone know an example of the FDS read/write function?
I'm working with this great example: https://github.com/bbbradsmith/NES-ca65 ... e/tree/fds
And I use these document use as reference: http://cmpslv2.starfree.jp/Famic/Famdis.htm / https://www.nesdev.org/disksystem.txt
I'm developing my original FDS game with original 3D printed disk. (https://x.com/HSA_Entmt/status/1829779467293900948)
My work is almost completed. But I couldn't implement save high score.
Does anyone know an example of the FDS read/write function?
I'm working with this great example: https://github.com/bbbradsmith/NES-ca65 ... e/tree/fds
And I use these document use as reference: http://cmpslv2.starfree.jp/Famic/Famdis.htm / https://www.nesdev.org/disksystem.txt
Re: Reading and writing data to disk in FDS
How do you reproduce the actual magnetic disk?
Re: Reading and writing data to disk in FDS
You'll want to use the BIOS routine to write a file located at $E239. This and others are documented here https://www.nesdev.org/wiki/FDS_BIOS#BIOS_calls
You'll want to ensure your save file is the last one on the side it is saved to, writing a file resets the "last file" pointer to whatever you write, so subsequent reads by the BIOS won't know about any files past the one you write.
You'll want to ensure your save file is the last one on the side it is saved to, writing a file resets the "last file" pointer to whatever you write, so subsequent reads by the BIOS won't know about any files past the one you write.
- TakuikaNinja
- Posts: 122
- Joined: Mon Jan 09, 2023 6:42 pm
- Location: New Zealand
- Contact:
Re: Reading and writing data to disk in FDS
I developed an FDS program which can dump the BIOS data to disk. It's implemented by calling WriteFile ($E239) in a loop to split the data into 1KiB files (to potentially get around write protection measures). Hopefully it gives some idea of how disk I/O is handled within a program: https://github.com/TakuikaNinja/FDS-BIOS-Dumper
P.S. I'd be happy to provide assistance in Japanese via private messages.
P.S. I'd be happy to provide assistance in Japanese via private messages.
We'll have to wait for OP to answer, but I wouldn't be surprised if the magnetic disk was made by trimming one found in a traditional floppy disk. Apparently "Backup Utilisation Techniques Part 10" contained a section on creating DIY disks using a plastic underlay (the kind that's placed underneath notebook pages while writing) and an 8" floppy. (Japanese Source)
-
- Posts: 4
- Joined: Sun Sep 29, 2024 6:40 am
Re: Reading and writing data to disk in FDS
Thanks for your reply.
I tried write new code. (Thank you, TakuikaNinja-San and segaloco-San!)
Full repository is: https://github.com/Hidetyo/FDS-Save-Load-Test/tree/main
This code works to read and write to disk. First, it read disk and displays 4 variables about 3 second. Second, it add 1 to each other and write to disk.
When I use this fds rom to FDS hardware, the motor will works. But variables won't changed.
Also I checked with FDSKey. When data saved, FDSKey displays "Wrong block CRC" message.
Because I don't want to use Nintendo engraved disk.
I apologize about my English skill.....
I tried write new code. (Thank you, TakuikaNinja-San and segaloco-San!)
Full repository is: https://github.com/Hidetyo/FDS-Save-Load-Test/tree/main
This code works to read and write to disk. First, it read disk and displays 4 variables about 3 second. Second, it add 1 to each other and write to disk.
When I use this fds rom to FDS hardware, the motor will works. But variables won't changed.
Also I checked with FDSKey. When data saved, FDSKey displays "Wrong block CRC" message.
Code: Select all
;
; This is main code:
;
.segment "FILE0_DAT"
main:
jsr as_clear_20191111 ; This is my compiler's code
jsr as_setaspal_20191111 ; This is my compiler's code
NUM1 = $000A
NUM2 = $000B
NUM3 = $000C
NUM4 = $000D
DataLoad:
jsr $E1B2 ; VINTWait
jsr $E1F8 ; Load Data
.word DiskID
.word LoadList
bne Error
beq NoData ; If data cannot find, variables will set 0
lda $4031 ; If data found, set variables
sta NUM1
lda $4031
sta NUM2
lda $4031
sta NUM3
lda $4031
sta NUM4
jmp Disp
Error: ;Error Beep
lda $4015
ora #%00000001
sta $4015
lda #%10111111
sta $4000
lda #%00101011
sta $4001
lda #%00000100
sta $4002
lda #%11111011
sta $4003
jmp Error
DiskID:
.byte $00 ; manufacturer
.byte "TST "
.byte $00 ; game version
.byte $00 ; side
.byte $00 ; disk
.byte $00 ; disk type
.byte $00 ; unknown
LoadList:
.byte $05, $FF
NoData:
lda #$00
sta NUM1
sta NUM2
sta NUM3
sta NUM4
jmp Disp
Disp: ;Display variables
sta $07FF
lda NUM1
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$4a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM2
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$6a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM3
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$8a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM4
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$aa
sta $042F
jsr as_point_20191111
lda $07FF
wait_seconds: ;Wait
lda $2002
bpl wait_seconds
ldx #0
loop:
lda $2002
bpl loop
inx
cpx #180
bne loop
DataSave:
inc NUM1
lda NUM1
sta $4024
inc NUM2
lda NUM2
sta $4024
inc NUM3
lda NUM3
sta $4024
inc NUM4
lda NUM4
sta $4024
jsr $E1B2 ;VINTWait
lda #5 ;FILE ID
jsr $E239 ;LoadData
.word DiskID
.word FileHeader
bne Error2
jmp end
Error2: ;Error Beep
lda $4015
ora #%00000001
sta $4015
lda #%10111111
sta $4000
lda #%00101011
sta $4001
lda #%00000100
sta $4002
lda #%11111011
sta $4003
jmp Error2
end:
jmp end
;End of my code
My 3D printed disk uses official retail magnetic disk unit. So I took it out from official disk...
Because I don't want to use Nintendo engraved disk.
I apologize about my English skill.....
Re: Reading and writing data to disk in FDS
If it helps, the function in question is here labeled as fds_file_write (line 198): https://gitlab.com/segaloco/fdsboot/-/b ... /src/sys.s
If it isn't working for you, you might strip this and the supporting bits out and incorporate the code in your program directly, at least for the time being to more effectively debug it.
Fun fact, several FDS games from Nintendo (and maybe others?) implement an anti-piracy mechanism involving a modified version of disk I/O that has a file count hard-coded into it, ignoring the count in the header. The routine is directly from the boot ROM save that the file count isn't read from disk. The result is you can hide an extra file on the disk that only this modified version of the routine can read. If the data isn't there, the game locks, assuming it was a copy made using stock I/O that wouldn't know anything about the extra file. This doesn't combat every mechanism, but does handle cases where the FDS unit itself is used to extract the disk by exploiting built-in I/O to move files to some sort of external non-volatile memory device.
If it isn't working for you, you might strip this and the supporting bits out and incorporate the code in your program directly, at least for the time being to more effectively debug it.
Fun fact, several FDS games from Nintendo (and maybe others?) implement an anti-piracy mechanism involving a modified version of disk I/O that has a file count hard-coded into it, ignoring the count in the header. The routine is directly from the boot ROM save that the file count isn't read from disk. The result is you can hide an extra file on the disk that only this modified version of the routine can read. If the data isn't there, the game locks, assuming it was a copy made using stock I/O that wouldn't know anything about the extra file. This doesn't combat every mechanism, but does handle cases where the FDS unit itself is used to extract the disk by exploiting built-in I/O to move files to some sort of external non-volatile memory device.
- TakuikaNinja
- Posts: 122
- Joined: Mon Jan 09, 2023 6:42 pm
- Location: New Zealand
- Contact:
Re: Reading and writing data to disk in FDS
The File Header struct used for saving a file to disk requires you to include data about the file: https://www.nesdev.org/wiki/FDS_BIOS#Fi ... _structureHSA Entertainment wrote: ↑Mon Sep 30, 2024 11:51 am Thanks for your reply.
I tried write new code. (Thank you, TakuikaNinja-San and segaloco-San!)
Full repository is: https://github.com/Hidetyo/FDS-Save-Load-Test/tree/main
This code works to read and write to disk. First, it read disk and displays 4 variables about 3 second. Second, it add 1 to each other and write to disk.
When I use this fds rom to FDS hardware, the motor will works. But variables won't changed.
Also I checked with FDSKey. When data saved, FDSKey displays "Wrong block CRC" message.
Code: Select all
; ; This is main code: ; .segment "FILE0_DAT" main: jsr as_clear_20191111 ; This is my compiler's code jsr as_setaspal_20191111 ; This is my compiler's code NUM1 = $000A NUM2 = $000B NUM3 = $000C NUM4 = $000D DataLoad: jsr $E1B2 ; VINTWait jsr $E1F8 ; Load Data .word DiskID .word LoadList bne Error beq NoData ; If data cannot find, variables will set 0 lda $4031 ; If data found, set variables sta NUM1 lda $4031 sta NUM2 lda $4031 sta NUM3 lda $4031 sta NUM4 jmp Disp Error: ;Error Beep lda $4015 ora #%00000001 sta $4015 lda #%10111111 sta $4000 lda #%00101011 sta $4001 lda #%00000100 sta $4002 lda #%11111011 sta $4003 jmp Error DiskID: .byte $00 ; manufacturer .byte "TST " .byte $00 ; game version .byte $00 ; side .byte $00 ; disk .byte $00 ; disk type .byte $00 ; unknown LoadList: .byte $05, $FF NoData: lda #$00 sta NUM1 sta NUM2 sta NUM3 sta NUM4 jmp Disp Disp: ;Display variables sta $07FF lda NUM1 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$4a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM2 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$6a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM3 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$8a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM4 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$aa sta $042F jsr as_point_20191111 lda $07FF wait_seconds: ;Wait lda $2002 bpl wait_seconds ldx #0 loop: lda $2002 bpl loop inx cpx #180 bne loop DataSave: inc NUM1 lda NUM1 sta $4024 inc NUM2 lda NUM2 sta $4024 inc NUM3 lda NUM3 sta $4024 inc NUM4 lda NUM4 sta $4024 jsr $E1B2 ;VINTWait lda #5 ;FILE ID jsr $E239 ;LoadData .word DiskID .word FileHeader bne Error2 jmp end Error2: ;Error Beep lda $4015 ora #%00000001 sta $4015 lda #%10111111 sta $4000 lda #%00101011 sta $4001 lda #%00000100 sta $4002 lda #%11111011 sta $4003 jmp Error2 end: jmp end ;End of my code
You seem to have reserved the space for it in zeropage like I did in my project, which you don't actually need to do when the file header block doesn't change between disk accesses. Its contents don't seem to be initialised before it's used by WriteFile, either. I apologise for misleading you with an atypical use case like that. The File Header struct should be placed in your main PRG code instead, with the proper values filled in.
I suppose it doesn't help that the wiki example code only covers disk loading. Maybe I should add an example of disk saving, too. That page really needs to be reorganised... EDIT: I've added the saving example and reorganised the error list.
-
- Posts: 4
- Joined: Sun Sep 29, 2024 6:40 am
Re: Reading and writing data to disk in FDS
Thank you! The new example is very nice.TakuikaNinja wrote: ↑Mon Sep 30, 2024 5:12 pmThe File Header struct used for saving a file to disk requires you to include data about the file: https://www.nesdev.org/wiki/FDS_BIOS#Fi ... _structureHSA Entertainment wrote: ↑Mon Sep 30, 2024 11:51 am Thanks for your reply.
I tried write new code. (Thank you, TakuikaNinja-San and segaloco-San!)
Full repository is: https://github.com/Hidetyo/FDS-Save-Load-Test/tree/main
This code works to read and write to disk. First, it read disk and displays 4 variables about 3 second. Second, it add 1 to each other and write to disk.
When I use this fds rom to FDS hardware, the motor will works. But variables won't changed.
Also I checked with FDSKey. When data saved, FDSKey displays "Wrong block CRC" message.
Code: Select all
; ; This is main code: ; .segment "FILE0_DAT" main: jsr as_clear_20191111 ; This is my compiler's code jsr as_setaspal_20191111 ; This is my compiler's code NUM1 = $000A NUM2 = $000B NUM3 = $000C NUM4 = $000D DataLoad: jsr $E1B2 ; VINTWait jsr $E1F8 ; Load Data .word DiskID .word LoadList bne Error beq NoData ; If data cannot find, variables will set 0 lda $4031 ; If data found, set variables sta NUM1 lda $4031 sta NUM2 lda $4031 sta NUM3 lda $4031 sta NUM4 jmp Disp Error: ;Error Beep lda $4015 ora #%00000001 sta $4015 lda #%10111111 sta $4000 lda #%00101011 sta $4001 lda #%00000100 sta $4002 lda #%11111011 sta $4003 jmp Error DiskID: .byte $00 ; manufacturer .byte "TST " .byte $00 ; game version .byte $00 ; side .byte $00 ; disk .byte $00 ; disk type .byte $00 ; unknown LoadList: .byte $05, $FF NoData: lda #$00 sta NUM1 sta NUM2 sta NUM3 sta NUM4 jmp Disp Disp: ;Display variables sta $07FF lda NUM1 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$4a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM2 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$6a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM3 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$8a sta $042F jsr as_point_20191111 lda $07FF sta $07FF lda NUM4 sta as_point lda $07FF sta $07FF lda #$21 sta $042E lda #$aa sta $042F jsr as_point_20191111 lda $07FF wait_seconds: ;Wait lda $2002 bpl wait_seconds ldx #0 loop: lda $2002 bpl loop inx cpx #180 bne loop DataSave: inc NUM1 lda NUM1 sta $4024 inc NUM2 lda NUM2 sta $4024 inc NUM3 lda NUM3 sta $4024 inc NUM4 lda NUM4 sta $4024 jsr $E1B2 ;VINTWait lda #5 ;FILE ID jsr $E239 ;LoadData .word DiskID .word FileHeader bne Error2 jmp end Error2: ;Error Beep lda $4015 ora #%00000001 sta $4015 lda #%10111111 sta $4000 lda #%00101011 sta $4001 lda #%00000100 sta $4002 lda #%11111011 sta $4003 jmp Error2 end: jmp end ;End of my code
You seem to have reserved the space for it in zeropage like I did in my project, which you don't actually need to do when the file header block doesn't change between disk accesses. Its contents don't seem to be initialised before it's used by WriteFile, either. I apologise for misleading you with an atypical use case like that. The File Header struct should be placed in your main PRG code instead, with the proper values filled in.
I suppose it doesn't help that the wiki example code only covers disk loading. Maybe I should add an example of disk saving, too. That page really needs to be reorganised... EDIT: I've added the saving example and reorganised the error list.
...But I couldn't make correct code. I changed code for only one variable and replace load and write method.
This code will load variable from file No.5 on the disk and save number "123" to the file.
This is new code:
Code: Select all
;
; This is main code:
;
.segment "FILE0_DAT"
main:
jsr as_clear_20191111 ; This is my compiler's code
jsr as_setaspal_20191111 ; This is my compiler's code
NUM1 = $000A
NUM2 = $000B
NUM3 = $000C
NUM4 = $000D
DataLoad:
jsr $E1B2 ; VINTWait
jsr $E1F8 ; Load Data
.word DiskID
.word LoadList
bne Error
lda $2001 ; If data found, set variables
sta NUM1
jmp Disp
Error: ;Error Loop
jmp Error
DiskID:
.byte $00 ; manufacturer
.byte "TST "
.byte $00 ; game version
.byte $00 ; side
.byte $00 ; disk
.byte $00 ; disk type
.byte $00 ; unknown
LoadList:
.byte $05, $FF
Disp: ;Display variables
sta $07FF
lda NUM1
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$4a
sta $042F
jsr as_point_20191111
lda $07FF
jmp wait_seconds ;Skip other variables display
sta $07FF
lda NUM2
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$6a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM3
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$8a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM4
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$aa
sta $042F
jsr as_point_20191111
lda $07FF
wait_seconds: ;Wait
lda $2002
bpl wait_seconds
ldx #0
loop:
lda $2002
bpl loop
inx
cpx #180
bne loop
DataSave:
lda #123
sta NUM1
jsr $E1B2 ;VINTWait
lda #$05 ;FILE ID
jsr $E239 ;SaveData
.word DiskID
.word FileHeader
bne Error2
Error2: ;Error Loop
jmp Error2
end:
jmp end
FileHeader: ; In this example, we are saving a game save to disk
.byte $05 ; file ID code (used by LoadFiles)
.byte "SAVEDATA" ; file name
.word $2001 ; load address
.word $1000 ; file data size
.byte $00 ; file type (PRG)
.word $000A ; source address of file data
.byte $00 ; source address type (RAM)
;End of my code
Before running:
Code: Select all
03 05 05 53 41 56 45 44 41 54 41 01 20 00 10 00 04 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Code: Select all
03 05 05 53 41 56 45 44 41 54 41 01 20 00 10 00 04 0A 00 FD 0F 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 E1 00 00 00 00 10 C0 40 35 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0 A4 E7 60 A4 A1 A4 E7 11 E6 83 E2 4E E2 80 9A 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 AA 05 02 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 61 A3 62 FA 02 05 04 00 00 0A 08 FD 07 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 E1 00 00 00 00 10 C0 40 35 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0 A4 E7 60 A4 A1 A4 E7 11 E6 83 E2 4E E2 80 9A 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 AA 05 02 05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 61 A3 62 FA 02 05 04 00 00
My questions are...
1. Should I use lda $*Data adress* when referencing a value from disk? And should the length of the file header be considered? (For example, if a saved data file starts with $2001, I use lda $2001)
2. When writing data to disk, should the “source address of file data” in the File Header indicate the address of the variable? (Within my code, I specify .word $000A to write NUM1.)
3. Can multiple variables be written to disk at the same time?
If it is too difficult for me, I will exclude the save function and release my game with only the current FDS sound support.
Thanks for your support.
Re: Reading and writing data to disk in FDS
Oh wow, I didn't know you could make that without some kind of special equipment.TakuikaNinja wrote: ↑Sun Sep 29, 2024 8:07 pmWe'll have to wait for OP to answer, but I wouldn't be surprised if the magnetic disk was made by trimming one found in a traditional floppy disk. Apparently "Backup Utilisation Techniques Part 10" contained a section on creating DIY disks using a plastic underlay (the kind that's placed underneath notebook pages while writing) and an 8" floppy. (Japanese Source)
Oh I see, that's what I thought but I sort of had hopes that someone were producing new magnetic disks.HSA Entertainment wrote: ↑Mon Sep 30, 2024 11:51 am My 3D printed disk uses official retail magnetic disk unit. So I took it out from official disk...
Because I don't want to use Nintendo engraved disk.
Thanks for doing that, I long thought the FDS pages was in need for some concrete examples, especially for loading and saving, but I haven't touched FDS coding for years.TakuikaNinja wrote: ↑Mon Sep 30, 2024 5:12 pm I suppose it doesn't help that the wiki example code only covers disk loading. Maybe I should add an example of disk saving, too. That page really needs to be reorganised... EDIT: I've added the saving example and reorganised the error list.
- TakuikaNinja
- Posts: 122
- Joined: Mon Jan 09, 2023 6:42 pm
- Location: New Zealand
- Contact:
Re: Reading and writing data to disk in FDS
There's a few problems I've noticed, which also tie into the questions you had:HSA Entertainment wrote: ↑Tue Oct 01, 2024 7:02 am So file was changed. But I cannot find my variable.
My questions are...
1. Should I use lda $*Data adress* when referencing a value from disk? And should the length of the file header be considered? (For example, if a saved data file starts with $2001, I use lda $2001)
2. When writing data to disk, should the “source address of file data” in the File Header indicate the address of the variable? (Within my code, I specify .word $000A to write NUM1.)
3. Can multiple variables be written to disk at the same time?
If it is too difficult for me, I will exclude the save function and release my game with only the current FDS sound support.
Thanks for your support.
- The first 16 bytes of zeropage ($0000~$000F) are often used by the FDS BIOS routines as temporary variables. The variables you're using for the disk saving test ($000A~$000D) may be conflicting with some routines. Try placing the variables in other sections of RAM (e.g. $0300~$07FF, assuming the $0200 page is for OAM DMA), or the PRG-RAM area ($6000~$DFFF).
- The load address must be the CPU address where the data should be loaded into, and the file data size should match the number of bytes you're trying to save. The address you specified here actually maps to a PPU register (PPUMASK), which is why you aren't getting the values back into RAM, let alone your variables. In this case, just use the same label you assigned to the first variable (same for the file data source address).
- Questions 1, 2: Your code is inconsistent when it comes to using variable/label names vs absolute address values, which has probably been the main source of confusion here. Modern assemblers let you define and use human-readable labels in place of address values. This applies to memory-mapped registers and FDS BIOS routine calls, too. I often just include pre-made files that assign labels to them, so I don't have to remember addresses every time.
- Question 3: Yes, the file data size can technically go up to $FFFF (some programs use abnormally large file sizes as a means of copy protection). So practically speaking, an unlimited amount of contiguous bytes can be saved/loaded per file. In fact, it's far more likely that you would run out of room to load the data to/from before you run out of disk space.
In the case of save data, you should serialise the game state into a contiguous byte stream (or multiple concatenated ones, if more than one save can be used) and solely use that data for disk saving. Disk loading is the opposite - after loading the serialised data (and presumably after the player selects the save data to be used), de-serialise the data back into the game state before running the main game. I suppose this can be applied to saving in general, whether it uses battery-backed SRAM, passwords, or something else. The only differences are that SRAM is generally more lenient (as it's often mapped to CPU memory and can therefore just be used as RAM), and that passwords are more strict (works better with a bit stream). Perhaps an article on game saving would be a good addition to the wiki? Error detection/correction should probably be covered as well.
-
- Posts: 4
- Joined: Sun Sep 29, 2024 6:40 am
Re: Reading and writing data to disk in FDS
Thank you! Finaly, I could make a code that works correct
And I bring it to my game code. It almost works!
Thank you for help me.
I want to make easy exsample for FDS audio and FDS Disk IO in the future.
This is code that works correct for people who has problem same with me:
And I bring it to my game code. It almost works!
Thank you for help me.
I want to make easy exsample for FDS audio and FDS Disk IO in the future.
This is code that works correct for people who has problem same with me:
Code: Select all
main:
NUM1 = $0300
NUM2 = $0301
NUM3 = $0302
NUM4 = $0303
DataLoad:
jsr $E1B2 ; VINTWait
jsr $E1F8 ; Load Data
.word DiskID
.word LoadList
bne Error
jmp Disp
Error: ;Error Loop
jmp Error
DiskID:
.byte $00 ; manufacturer
.byte "TST "
.byte $00 ; game version
.byte $00 ; side
.byte $00 ; disk
.byte $00 ; disk type
.byte $00 ; unknown
LoadList:
.byte $05, $FF
Disp: ;Display variables
sta $07FF
lda NUM1
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$4a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM2
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$6a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM3
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$8a
sta $042F
jsr as_point_20191111
lda $07FF
sta $07FF
lda NUM4
sta as_point
lda $07FF
sta $07FF
lda #$21
sta $042E
lda #$aa
sta $042F
jsr as_point_20191111
lda $07FF
jmp wait_seconds
wait_seconds: ;Wait
lda $2002
bpl wait_seconds
ldx #0
loop:
lda $2002
bpl loop
inx
cpx #180
bne loop
DataSave:
lda #114
sta NUM1
lda #120
sta NUM2
lda #045
sta NUM3
lda #076
sta NUM4
jsr $E1B2 ;VINTWait
lda #$05 ;FILE ID
jsr $E239 ;SaveData
.word DiskID
.word FileHeader
bne Error2
Error2: ;Error Loop
jmp Error2
end:
jmp end
FileHeader: ; In this example, we are saving a game save to disk
.byte $05 ; file ID code (used by LoadFiles)
.byte "SAVEDATA" ; file name
.word NUM1 ; load address
.word $0004 ; file data size
.byte $00 ; file type (PRG)
.word NUM1 ; source address of file data
.byte $00 ; source address type (RAM)
;End of code