How to reinit 16k expansion?

Basic and Machine Language

Moderator: Moderators

Post Reply
xavier
Vic 20 Nerd
Posts: 981
Joined: Wed Jan 07, 2015 2:20 pm
Location: France

How to reinit 16k expansion?

Post by xavier »

Hi all,
I actually type in a basic program from Hebdogiciel :
http://download.abandonware.org/magazin ... 098/03.jpg

And I had to reinit the 16K expansion using:
POKE642,30:POKE0,108:POKE1,0:POKE2,192:SYS0
And the game seem working properly!
But, you had to type in the line on the Basic prompt.

I include the generic loader.

Code: Select all

!- 16k loader.
11 POKE642,30
12 POKE36869,240:POKE36866,PEEK(36866)OR128
13 POKE648,30
268 POKE780,0
274 POKE44,32:POKE8192,0:CLR
277 PRINT"{clear}{home}{down*13}   un instant s.v.p"
280 PRINT"{home}{black}new":PRINT"{down*2}load"+CHR$(34)+"meurtrem1.prg"+CHR$(34)+",8"
283 POKE198,8:POKE631,19:POKE632,13:POKE633,13:POKE634,82:POKE635,85:POKE636,78:POKE637,13
... But, the memory seem to be decay and user's graphics aren't displayed!

Is there any ROM call (using SYSxxx) to script the first line?
(The SYS0 clear and break the basic program!)

A script in a loader file, will be more convenient to launch the basic game, if it avoid to need this ugly command!
I can't keep in mind that we had to write " Type: POKE642,30:POKE0,108:POKE1,0:POKE2,192:SYS0 and launch the game" ... on the tape/disk cover!

A simple :
10 PRINT "{clear}VALIDATE THE NEXT LINE AND LOAD THE GAME"
20 PRINT "POKE642,30:POKE0,108:POKE1,0:POKE2,192:SYS0{home}{down}":END

... for a tape... "LOAD" or the "something run/stop"
But on a disk, the name is too long! :mrgreen:
User avatar
eslapion
ultimate expander
Posts: 5458
Joined: Fri Jun 23, 2006 7:50 pm
Location: Canada
Occupation: 8bit addict

Re: How to reinit 16k expansion?

Post by eslapion »

La commande POKE642,30 change le début de la région de mémoire accessible au BASIC alors c'est évident qu'il est impossible de mettre une commande pareille à l'intérieur d'un programme en BASIC sauf à la toute fin pour en charger un autre.

La valeur normale de cette adresse est 18 lorsqu'on a un expansion de mémoire 8k ou plus. Placer 30 indique donc que tu réserve (30-18=12) 12 pages de 256 octets (3072 octets) pour les graphiques.

Pour faire ce que tu veux faire avec ton pre-loader il faudrait faire ça différemment. Le jeux Sword of Fargoal fait ça en mettant la commande LOAD dans le tampon du clavier.

Code: Select all

1 POKE36879,8:POKE36869,205;PRINT"[CTRL-2]"
2 S$="LOAD"+CHR$(34)+",8,1:"+CHR$(131)
3 FORT=1TOLEN(S$):POKE631+T,ASC(MID$(S$,T)):NEXT:POKE198,T
4 POKE642,22:POKE44,22:POKE46,22;POKE5632,0:POKE5633,0:POKE5634,0:NEW
Ce loader réserve moins de mémoire graphique que ton code car il arrête à la page 22 au lieu de la page 30 (22-18=4 pages donc 4*256=1024 octets graphiques) mais le principe est le même.

Non seulement ce code utilise le tampon clavier pour envoyer la commande LOAD mais en plus, il prend bien soin de réajuster TOUS les pointeurs du BASIC pour débuter à la page 22 et pas seulement le pointeur du début de mémoire. De plus, les 3 derniers POKE s'assurent qu'il n'y a pas de cochonnerie restante dans la mémoire qui pourraient interférer.

Je suis certain que tu peux modifier ce "loader" pour l'adapter à tes besoins.

La dernière ligne de ton loader:

Code: Select all

:POKE631,19:POKE632,13:POKE633,13:POKE634,82:POKE635,85:POKE636,78:POKE637,13
devrait faire

Code: Select all

[CLR](return)(return)RUN(return)
mais en réalité, CHR$(13) est un retour de chariot AFFICHÉ. Pour un vrai RETURN effectué, il faut utiliser le code 131.
Be normal.
xavier
Vic 20 Nerd
Posts: 981
Joined: Wed Jan 07, 2015 2:20 pm
Location: France

Re: How to reinit 16k expansion?

Post by xavier »

Many thanks Eslapion, i will get a try to pre-load the keyboard buffer!
In the previous loader, i had to change the screen buffer...
I will try and check the SYS0 command using the kb buffer. :?

Or use a variant of the "Sword of Fargoal" loader. :D
mais en réalité, CHR$(13) est un retour de chariot AFFICHÉ. Pour un vrai RETURN effectué, il faut utiliser le code 131
Wonderfull !
The CHR$(131) is the "Basic line" return ?!?
If poked at the end of line, it avoid the "?Systaxe error" and return the begin of line !!!
Cool!

Thanks!

[EDIT] tryed: not working, the SYS0 seem to erase the kb buffer!
0 print"{clear}":POKE36879,8:poke36869,240:
2 S$="poke0,108:poke1,0:poke2,192:sys0"+CHR$(131)+"load"+CHR$(34)+"meurtrem1.prg"+CHR$(34)+",8,1:"+CHR$(131)
3 FORT=1TOLEN(S$):POKE631+T,ASC(MID$(S$,T)):NEXT:POKE198,T
4 POKE642,30:POKE44,30:POKE46,30:POKE5632,0:POKE5633,0:POKE5634,0:NEW
xavier
Vic 20 Nerd
Posts: 981
Joined: Wed Jan 07, 2015 2:20 pm
Location: France

Re: How to reinit 16k expansion?

Post by xavier »

0 print"{clear}":POKE36879,8:poke36869,206:PRINT"[CTRL-2]"
2 S$="load"+CHR$(34)+"meurtrem1.prg"+CHR$(34)+",8"+CHR$(131)+"run"+CHR$(131)
3 FORT=1TOLEN(S$):POKE631+T,ASC(MID$(S$,T)):NEXT:POKE198,T
4 POKE642,30:POKE44,30:POKE46,30:POKE5632,0:POKE5633,0:POKE5634,0:NEW
No way !
Someting's wrong.
May be a out of memory ...

A "SYS0" seem to be the key.
But, i don't know what the poke 0,1 and 2 do!
It's not the ROM, but seem to be some Basic variables.

Note:
poke642,30:poke0,108:poke1,0:poke2,192:sys0
load"meurtrem1.prg",8
RUN
is working...

But, load"meurtrem1.prg",8,1
Don't work... "syntaxe error" when return is pressed (memory error!) (compiled with 16k ram pack)

poke642,30:poke0,108:poke1,0:poke2,192:NEW
load"meurtrem1.prg",8
RUN
Basic program splited and the end is garbages!

incude the faulty prg program...
meurtrem1.zip
(2.42 KiB) Downloaded 71 times
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Re: How to reinit 16k expansion?

Post by tlr »

xavier wrote:A "SYS0" seem to be the key.
But, i don't know what the poke 0,1 and 2 do!
It's not the ROM, but seem to be some Basic variables.

Note:
poke642,30:poke0,108:poke1,0:poke2,192:sys0
load"meurtrem1.prg",8
RUN
is working...
642,30 sets membot to $1e00. poke0 ... poke2 places the instruction JMP ($c000) at $00 and the sys executes it.
This instruction will restart basic using the new membot, i.e basic only uses $1e01 and up after this.
xavier wrote:But, load"meurtrem1.prg",8,1
Don't work... "syntaxe error" when return is pressed (memory error!) (compiled with 16k ram pack)
The load address of the file is $1201. If you use ,1 it will be force loaded to $1201 instead of $1e01.
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Re: How to reinit 16k expansion?

Post by tlr »

This should do it:

Code: Select all

10 PRINT"{clr/home}POKE642,30:POKE44,30:POKE7680,0:NEW":PRINT:PRINT
20 PRINT"LOAD"CHR$(34)"MEURTREM1.PRG"CHR$(34)",8":PRINT:PRINT:PRINT:PRINT:PRINT
30 PRINT"RUN"
40 POKE631,19:POKE632,13:POKE633,13:POKE634,13
50 POKE198,4
here: loader.prg

And most of what I've said was probably in eslapions comments but my french is a little rusty, so...
xavier
Vic 20 Nerd
Posts: 981
Joined: Wed Jan 07, 2015 2:20 pm
Location: France

Re: How to reinit 16k expansion?

Post by xavier »

NOT VERY LOL...
It work... :shock:
Same recipe, but 30 years to improve it!

Fill screen buffer:
10 PRINT"{clr/home}POKE642,30:POKE44,30:POKE7680,0:NEW":PRINT:PRINT
20 PRINT"LOAD"CHR$(34)"MEURTREM1.PRG"CHR$(34)",8":PRINT:PRINT:PRINT:PRINT:PRINT
30 PRINT"RUN"


Fill keyboard buffer:
40 POKE631,19:POKE632,13:POKE633,13:POKE634,13

Number of key stroke:
50 POKE198,4
loader_screen.jpg
loader_screen.jpg (11.56 KiB) Viewed 1827 times
[HOME]
POKE642,30:POKE44,30:POKE7680,0:NEW >>> init 16k ram bottom memory offset.
[RETURN]
LOAD"MEURTREM1.PRG",8 >>>LOAD the game to the current bottom Basic memory! (tx TLR)
[RETURN]
RUN >>> RUN IT!
[RETURN]

POKE36879,8:poke36869,206
Video memory isn't reset.


eslapion, I compile my text ocr with "VIC20PrgGen.exe" using a 16k expansion!
The bottom memory offset seem to be @ POKE642,32, and a load "...,8,1:" seem to force the basic start to a wrong offset... if POKE642,30 is used. (>tlr)
A simply load"xxx",8 relocate the basic to defaut basic set!
And seem reinit the right screen memory offset.

Vic20 memory get hard in case of expansion is in use...


Thanks eslapion!
And Thanks tlr!
User avatar
Mike
Herr VC
Posts: 4830
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: How to reinit 16k expansion?

Post by Mike »

xavier wrote:Vic20 memory get hard in case of expansion is in use ...
Not really. I'm following up this with a slightly longer post. Sorry in advance for that.

It all boils down to what contiguous address range in RAM is available for a BASIC program and its variables, what address range of RAM is accessible for the VIC chip and whether these two address ranges might collide and need to be separated.


The addressable memory for the VIC chip is fixed, and doesn't change regardless what external expansions are there: only the RAM at addresses $0000..$03FF and $1000..$1FFF and the character ROM are 'visible' for VIC. $0000..$03FF are used by the OS. So for the text screen, it makes sense to place it at either end of the range $1000..$1FFF to maximize the amount of contiguous RAM for BASIC:

1. Actually, on an unexpanded VIC-20, BASIC uses $1000..$1DFF, and the text screen is placed at $1E00 so it can be left there, when the smallest available RAM expansion, +3K, is added.

2. The +3K RAM expansion is mapped in at $0400..$0FFF, BASIC uses $0400..$1DFF, the text screen keeps its position at $1E00. It would not be possible to move the text screen to $0400 and let BASIC use $0600..$1FFF instead!

3. When a +8K or bigger RAM expansion is present, it is mapped to $2000 following. To maximize the available space for BASIC, the text screen is therefore moved down to the lower end of the range $1000..$1FFF accessible by VIC. BASIC starts at $1200 and extends all the way up to what the RAM expansion delivers ($3FFF for +8K, $5FFF for +16K and $7FFF for +24K).

I put a diagram of these 3 cases into the sticky thread "VIC-20 Memory Layout" - see the boxes for BASIC memory.


If there is a +3K RAM expansion present alongside a bigger RAM expansion, the text screen still can't be moved down to $0400. The lowest possible address again is $1000. The bigger RAM expansion takes precedence, thus the +3K RAM expansion is blocked from use by BASIC, which is also reflected in the number of BYTES FREE (it stays the same as for +8K/+16K/+24K without the extra +3K). But the RAM is still there, and can be used by machine language programs, for example.

The 8K address range at $A000..$BFFF (BLK5) can't form a contiguous block with the 'main' RAM in any case, and thus likewise isn't shown as extra BYTES FREE if it's populated with RAM. It's still usable by machine language programs.


With user defined graphics, VIC not only needs to read text screen data from its restricted memory range, but also the character matrixes of the user defined graphics. It must be ensured, that the user defined graphics do not collide with the BASIC program or its variables: when the program POKEs the character matrixes from DATA lines, it could inadvertently overwrite itself; likewise the variables (especially strings) might overwrite the character data that has already been defined in RAM.

There are mainly two techniques to keep character data and text screen separated from the program and its variables:

1. Lowering the roof. That's what's being done with POKE55,...:POKE56,...:CLR. That method is mainly used on an unexpanded VIC-20, or with a +3K RAM expansion. The memory arrangement then is: |program/variables|character data|text screen|. The BASIC program itself stays at the same place.

2. Raising the start of BASIC. That method is necessary, as soon as a bigger RAM expansion (+8K or more) is there. If done otherwise, lowering the roof would completely block the RAM expansion from BASIC use (again, text screen and character data need to reside in the range $1000..$1FFF!). Raising the BASIC start is rather difficult to do (to say the least) from an already loaded and running BASIC program, as the program itself and its variables would need to be shifted in memory, and lots of pointers would need to be adjusted while it is running. Instead, the BASIC start is adjusted before. Either manually (those POKE and SYS incantations), or with boot loaders (and lots of simulated keypresses), and then the program is loaded to and run from a place, where it again cannot collide with either text screen or user defined graphics. The memory arrangement then is: |text screen|character data|program/variables| or |character data|text screen|program/variables|.


Finally, some remarks about how the addresses 43/44, 55/56, 641/642 and 643/644 are used by BASIC and KERNAL:

- directly after a reset/power-on, the KERNAL scans the available contiguous RAM address range 'around' the internal RAM, corrects it for the aforementioned restrictions of the VIC chip, and stores the result in 641/642 (bottom of RAM, RAMBOT) and 643/644 (top of RAM, RAMTOP)

- when BASIC is cold-started after reset/power-on, it takes the value in 641/642, adds 1, and writes the result to the BASIC start pointer in 43/44; it then copies the value in 643/644 to 55/56 as pointer to 'end of memory for BASIC'. A 0-byte is placed right before the BASIC start to signify a line end for the interpreter, and then a automatic NEW command writes another two 0-bytes directly behind - this is actually an empty BASIC program! That's why you see 3583 and not 3584 BYTES FREE in the start-up prompt (and PRINT FRE(0) gives 3581).

Now it is possible to execute most parts of the reset routine, excluding the RAM check, with SYS64818 - instead providing own, redefined values for 641..644. As 641 and 643 most probably contain a zero from an earlier (power-on) reset, most often only 642 and 644 (and 648 for the screen base) are changed. So instead of POKE642,30:POKE0,108:POKE1,0:POKE2,192:SYS0, the line:

Code: Select all

POKE642,30:SYS64818
would have the same effect: returning you to the start-up prompt, with slightly less available memory, which has been protected for the program to use text screen and character data. As you have noted, that method is particularly unfit for a batch procedure, as the executing program is stopped, and even cleared from memory.

Changing 43/44, and POKEing the 0 in front of it, won't make it necessary to restart BASIC, so it can be done as batch. With a boot loader, two methods are possible:

1. PRINTing two lines with POKE43,...:POKE44,...:POKE....,0:NEW and LOAD"...",8 and executing both with simulated key presses. That's how you implemented it in your posting before.

2. PRINTing just LOAD"...",8, and changing 43/44 from *inside* the program, which however comes in effect only just as the NEW is executed! Simulated key presses ({HOME}, and {RUN} -> LOAD + CR + RUN + CR) then execute the LOAD command and autostart the client program. This method requires much less thought on the screen layout:

Code: Select all

10 PRINT"{CLR}LOAD"CHR$(34)"..."CHR$(34)",8"
20 POKE631,19:POKE632,131:POKE198,2
30 POKE43,...:POKE44,...:POKE....,0:NEW
POKE642,... is not necessary here, as no BASIC cold-start is performed which would re-init 43/44 from 641/642. But you definitely would want to define the low-byte of the BASIC start pointer. In your concrete case, the boot loader then looks like this:

Code: Select all

10 PRINT"{CLR}LOAD"CHR$(34)"MEURTREM1.PRG"CHR$(34)",8"
20 POKE631,19:POKE632,131:POKE198,2
30 POKE43,1:POKE44,30:POKE7680,0:NEW
Greetings,

Michael
Last edited by Mike on Tue Mar 15, 2016 3:19 am, edited 1 time in total.
xavier
Vic 20 Nerd
Posts: 981
Joined: Wed Jan 07, 2015 2:20 pm
Location: France

Re: How to reinit 16k expansion?

Post by xavier »

:shock:
I'm impressed!
Thanks Mike.

"Meurtre au Manoir" is available.
http://sleepingelephant.com/ipw-web/bul ... &start=210
Post Reply