| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Loading and saving to disk using kernel
Assume: Machine booted from cart. Cart ROM at $8000-$bfff. IO at $Dxxx and KERNAL at $e000-$ffff
What calls do I have to do to use KERNEL load/save?
What RAM and ZP will be trashed by this?
How will it affect my IRQs? (I have CIA1 and raster IRQs running via $0314/15) |
|
| |
Scan
Registered: Dec 2015 Posts: 110 |
I currently use this to load levels in a game I've been working on, but I wouldn't recommend using kernal calls for doing this. If you don't reset the IO vectors first some unexpected results might occur. For example, if you have the Final Cartridge 3 enabled this will blank the screen while loading. This also does not play nice with interrupts.
.const SETLFS = $ffba
.const SETNAM = $ffbd
.const LOAD = $ffd5
load_level: lda #fname_end-fname
ldx #<fname
ldy #>fname
jsr SETNAM // call setnam
ldx $ba // last used device number
bne !+
ldx #$08 // default to device 8
!: ldy #$00 // $00 means: load to new address
jsr SETLFS // call setlfs
ldx #<level_address
ldy #>level_address
lda #$00 // $00 means: load to memory (not verify)
jsr LOAD // call load
rts
// most likely errors:
// a = $05 (device not present)
// a = $04 (file not found)
// a = $1d (load error)
// a = $00 (break, run/stop has been pressed during loading) // not used
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
I know how to load and save and that they toggles interrupts etc. That is not what I’m asking for though. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Check the reset code here:
https://sourceforge.net/p/vice-emu/code/HEAD/tree/testprogs/C64..
Maybe you can go even more minimal if only load/save is needed.
The kernal touches nothing below $90 if I recall correctly. The screen editor uses quite a lot so skipping $ff5b will probably save you a bunch. |
| |
enthusi
Registered: May 2004 Posts: 675 |
You can use vice(monitor) to trace touched areas.
memmapzap (mmzap) to reset stats
memmapshow (mmsh)
Syntax: memmapshow [<mask>] [<address_opt_range>]
(the mask is a single byte with bit flags).
This is quite helpful and would be a good start, I think.
I usually just buffer the whole ZP somewhere before using kernal routines from within a game or such. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Awesome guys, thanks! |
| |
Flavioweb
Registered: Nov 2011 Posts: 447 |
In my experience, if we use these kernal subroutines to set/load/save:
$FFE7, $FFBD, $FFBA, $FFC0, $FFC6, $FFCF, $FFC3, $FFCC, $FFC9, $FFD2
kernal uses these zero page locations:
$90, $91, $93, $94, $95, $98, $99, $9A, $9B, $9D, $A3, $A4, $AC, $AD, $AE, $AF, $B7, $B8, $B9, $BA, $BB, $BC, $C1, $C2.
We start from the assumption that system was already setup (using some code like TLR stated above).
Irq flag is set by kernal during all the IEC transfer time, then cleared.
This mean your own IRQ code should be delayed or you may have some unwanted side effects, according to what your code does.
If vectors ram still untouched, you can simply do nothing with locations $031A-$0333 (apart init them at start). Otherwise you need to backup/restore or kernal save/load may crash at some point...
These are my 2 cents =) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
duh! its KERNAL, not kernel. |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
raster irqs survive kernAl load, but they'll experience lots of SEI periods as big as half or more than a frame rarely.
just start a kernAl friendly music player raster irq which returns to basic, then you can load, and observe how the jsr call is delayed (inc/dec d020 is handy) |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: In my experience, if we use these kernal subroutines to set/load/save:
$FFE7, $FFBD, $FFBA, $FFC0, $FFC6, $FFCF, $FFC3, $FFCC, $FFC9, $FFD2
kernal uses these zero page locations:
$90, $91, $93, $94, $95, $98, $99, $9A, $9B, $9D, $A3, $A4, $AC, $AD, $AE, $AF, $B7, $B8, $B9, $BA, $BB, $BC, $C1, $C2.
We start from the assumption that system was already setup (using some code like TLR stated above).
Irq flag is set by kernal during all the IEC transfer time, then cleared.
This mean your own IRQ code should be delayed or you may have some unwanted side effects, according to what your code does.
If vectors ram still untouched, you can simply do nothing with locations $031A-$0333 (apart init them at start). Otherwise you need to backup/restore or kernal save/load may crash at some point...
These are my 2 cents =)
Big thanks. I’ll make ld65 keep those areas clean and try it! :) |
| |
Danzig
Registered: Jun 2002 Posts: 429 |
@JackAsser: Don't know if its of any value for you but if you use $ee13 you can jump to $ee20 instead and use
LDA #$00
STA $A5
JSR $EE85
JSR $EEA9
BPL *-3
SEI
jsr $ee20
with moving the SEI below the BPL the routine just rips ~30 rasterlines while loading. One might call it "pretty cheap irq loader" :-D
Org (KERNAL):
.,EE13 78 SEI
.,EE14 A9 00 LDA #$00
.,EE16 85 A5 STA $A5
.,EE18 20 85 EE JSR $EE85
.,EE1B 20 A9 EE JSR $EEA9
.,EE1E 10 FB BPL $EE1B
PS: AFAIR the source of this "trick" was some issue of "64er" |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: @JackAsser: Don't know if its of any value for you but if you use $ee13 you can jump to $ee20 instead and use
LDA #$00
STA $A5
JSR $EE85
JSR $EEA9
BPL *-3
SEI
jsr $ee20
with moving the SEI below the BPL the routine just rips ~30 rasterlines while loading. One might call it "pretty cheap irq loader" :-D
Org (KERNAL):
.,EE13 78 SEI
.,EE14 A9 00 LDA #$00
.,EE16 85 A5 STA $A5
.,EE18 20 85 EE JSR $EE85
.,EE1B 20 A9 EE JSR $EEA9
.,EE1E 10 FB BPL $EE1B
PS: AFAIR the source of this "trick" was some issue of "64er"
Thanks! I’ll keep it simple and just clear the area where the IRQ was needed though. I have a multiplexed sprite overlay which will get distorted even with the trick u mentioned. So let’s forget about IRQ and focus on Kernel memory footprint. |
| |
Flavioweb
Registered: Nov 2011 Posts: 447 |
Quoting JackAsserI have a multiplexed sprite overlay which will get distorted even with the trick u mentioned. So let’s forget about IRQ and focus on Kernel memory footprint.
Mmmm... if you have 8 sprites in a row on the screen, Iec transfers goes out of sync, even without any Irq code running...
Is safe turn off all sprites during save/load... |
| |
Grue
Registered: Dec 2001 Posts: 146 |
While these tricks are nice and clever keep in mind that it will break compability with alternative kernals.
Quoting Danzig@JackAsser: Don't know if its of any value for you but if you use $ee13 you can jump to $ee20 instead and use
LDA #$00
STA $A5
JSR $EE85
JSR $EEA9
BPL *-3
SEI
jsr $ee20
with moving the SEI below the BPL the routine just rips ~30 rasterlines while loading. One might call it "pretty cheap irq loader" :-D
Org (KERNAL):
.,EE13 78 SEI
.,EE14 A9 00 LDA #$00
.,EE16 85 A5 STA $A5
.,EE18 20 85 EE JSR $EE85
.,EE1B 20 A9 EE JSR $EEA9
.,EE1E 10 FB BPL $EE1B
PS: AFAIR the source of this "trick" was some issue of "64er" |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Yeah, I keep it simple and blank the screen. Speaking of alternative Kernels... what about their memory footprint while loading/saving? |
| |
Flavioweb
Registered: Nov 2011 Posts: 447 |
To avoid problems with the pletora of alternative fl, you can just backup/reset/restore the vectors.
But should be interesting to investigate this... |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: To avoid problems with the pletora of alternative fl, you can just backup/reset/restore the vectors.
But should be interesting to investigate this...
The vectors are one thing, but I would imagine an alternative kernel to perhaps reserve a 256 byte sector buffer for speed etc no? Or are they all "compatible" to each other? Or is it simply assumed that ZP and $200-$3ff is a no-go for own code when it comes to kernel compatibility? |
| |
cadaver
Registered: Feb 2002 Posts: 1153 |
I go by the assumption that any alternative kernal will not use at least more memory or more ZP locations, may come to yet bite my ass :)
Outside ZP starting your own memory use from $0334 should be OK, no need to avoid $0334-$03ff range unless you use tape IO. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1378 |
Quoting OswaldkernAl
And Betty when you call me you can calllll, meeeee, Al :) |
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
Code used for Berzerk Redux. I used the disk drive for hiscore storage with an optional custom load/save: https://github.com/martinpiper/C64Public/blob/master/BerzerkRed..
Citadel2 cartridge code, works with kernal replacement and CBM80 boot carts (EF and GMod2). Also tests cart banking: https://github.com/martinpiper/C64Public/blob/master/Citadel2/C.. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: Code used for Berzerk Redux. I used the disk drive for hiscore storage with an optional custom load/save: https://github.com/martinpiper/C64Public/blob/master/BerzerkRed..
Citadel2 cartridge code, works with kernal replacement and CBM80 boot carts (EF and GMod2). Also tests cart banking: https://github.com/martinpiper/C64Public/blob/master/Citadel2/C..
Awesome Martin! Thanks! |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
I saved a file with this routine from codebase:
https://codebase64.org/doku.php?id=base:saving_a_file
That works fine.
But when I want to load it again via
https://codebase64.org/doku.php?id=base:loading_a_file
it never returns from JSR $FFD5. It gets stuck in some loop at $EE30.
I'm not using any ZP adresses above $8f. But I did disable timer interrupts earlier:
lda #$7f
sta $dc0d
sta $dd0d
lda $dc0d
lda $dd0d
Enabling them before calling the load routine doesn't seem to help. I also disabled raster IRQs before calling the routine:
sei
lda #0
sta $d01a
inc $d019
lda #$37
sta $01 ;I used $fffe and $ffff, so this should be fine
The call to the load routine is done from main.
Does anybody have an idea why the load routine doesn't return and/or suggestions what I could try? |
| |
chatGPZ
Registered: Dec 2001 Posts: 11109 |
i'd try calling the IORESET (or whatever its called) kernal call before, if that does the trick strip it down :) |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
Thanks, but calling $FDA3 (IOINIT) doesn't help. |
| |
oziphantom
Registered: Oct 2014 Posts: 478 |
have you made an intentional or unintentional modifications to dd02/3 |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
Intentional no, unintentional unlikely. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
dd02 and dd03 was my thought also initially but $fda3 resets those.
Perhaps you have fiddled with the IEC bits in $dd00 and left the bus in a bad state? The drive could be hanging waiting for something to complete perhaps? |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
It looks a bit as if something went wrong while saving the file, althoug no error was returned. When I try to load the file directly from Basic after a cold start with load "*",8 or load "*",8,1 the same problem happens. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Well, then it was a red herring... |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
It was a bug in my code that calls the save routine (as you probably already suspected). Sorry about that. Thanks for your suggestions. They still helped me. |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
Care to explain what exactly the bug was? Could help others to prevent a similar error. =) |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
I could talk all day about the silly bugs I make. The file start and end addresses were set incorrectly.
I noticed some emulator differences: micro64 prints messages like "searching for", but Vice and Hox don't. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11109 |
You should not see any such differences - this is a kernal thing. You might have another bug - related to non initialized RAM (thats where the emulators differ). |
| |
Rastah Bar
Registered: Oct 2012 Posts: 336 |
Thanks for the hint. MSGFLG ($9D) was the culprit. Fast loading in micro64 sets this to Direct Mode. |