Initiation in Saturn
 
 

First of all, download: ADS v5.2 if you have Hp48gx. If not, install a fast editor: Eden v2.0 and Asm v1.0
 
Introduction
 

SATURN is the name of the microprocessor of the HP48. This chip is used in many HP models. The SATURN is very powerful. To compare with your video game console, although the SATURN is a 4 bit chip, it is sometimes even possible to work with 64 bits! To compare with your personal computer, the SATURN chip has an internal clock of 2 MHz for the HP48S(X), and 4 MHz for the HP48G(X), which makes it possible to create fast and powerful programs! But before jumping ahead into programming in assembler, it is necessary for us to study the working procedure of the SATURN chip.
 
 

Operation
 
 
The SATURN is a whole microprocessor. Like most microprocessors, it knows only 0's and 1's. That's called the binary system. In binary, only 0 and 1 are used. It is inconceivable to program in binary, so one has to resort to the hexadecimal system. In hexadecimal, there are 16 digits at our disposal, (0123456789ABCDEF) contrary to the binary's two digits, (01) and the decimal system, with 10 of them (0123456789). The use of the Hexadecimal base is not an imagination of the programmers, but allows better reading from these 0's and 1's. Indeed, four binary digits, (ex: # 0101b) can be shown in only one hexadecimal figure, (ex # 5h). A binary digit (0 or 1) is also called a bit. A succession of 4 bits is called a four-bit nybble (sometimes nibble), with a byte being a succession of 8 bits.

 

To summarize
 

A fragment of program in binary will resemble: 00110101011100101111010101001100
Let us cut out it in 8 four-bit bytes: 0011 0101 0111 0010 1111 0101 0100 1100
Let us transpose these 8 four-bit bytes in 8 Hexadecimal digits: C A E 4 F A 2 3
What gives us: CAE4FA23
 

 
What is more readable all the same, but still incomprehensible!
 

An instruction of the SATURN corresponds to a succession of some hexadecimal figures. For example, the instruction which extinguishes the screen of the HP is coded by: 8FDBB10. The assembler was born when one said oneself that it would be more convenient to associate a name of function with each instruction of the SATURN. Out of assembler, one glad to write the name of the function (also called: mnemonics) in our program. Tool called: ASSEMBLER makes it possible to replace these names of function by the corresponding hexadecimal codes. Thus the language of assembler was born. It should be noted that there is a table or are indexed all the functions of the SATURN, as well as the corresponding codes, one calls this table: Count of the mnemonic ones.

But let us take a simple example: The name of the instruction which makes it possible to extinguish the screen is: GOSBVL 01BBD What corresponds in fact to 8FDBB10 in machine language, or rather with: 1000111111011011101100010000 into binary. It will be noticed that the mnemonic ones are very useful all the same! Thus a program out of assembler is nothing different but a continuation mnemonic, which one must assemble using tool called 'assembler' to be able to carry out this program. But let us see all the functions which can fulfill the SATURN.
 

Registers of the SATURN
 

The SATURN calculation into hexadecimal, i.e. following a base of 16 digits which are: 0123456789ABCDEF. Thus, to write #14d in a program, we will have to write: # Eh. Here the table of correspondence between these two bases:

 

Base 10
Base 16
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
100
255
..
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
10
64
FF
..
  
 One gathers specifications of the SATURN according to several registers. The concept of registers will be employed with many recoveries, thus are attentive.
 
There are several kinds of registers:

 

Registers of calculation: A,B,C,D 
Registers of backup: R0,R1,R2,R3,R4 
Pointer registers: D0,D1 
The instruction counter: PC 
Inputs and outputs: OUT/IN 
The pile of the returns: RSTK 
Flags: ST, HST 
The pointer of fields: P
 
Let us analyze each one of these registers in detail:
 
 
Registers of calculation:
 
Fields:

 

There are 4 registers of calculations: A,B,C and D. If it can appear similar, know that registers: A and C are most important. All calculations of your HP pass by these registers. It is thus necessary to include/understand their operation well. These registers can accomodate 64 bits, that is to say 16 four-bit bytes. One is useful oneself of registers A and C for reading and writing in memory. Only the contents of registers A,B,C and D can be the subject of a processing. One of the assets major of the SATURN authorizes us to limit this processing to a portion given of this register of processing, and this according to the following table:

 Have well this table with the spirit, it will be very useful thereafter for you:
 
Division in fields of the 16 four-bit bytes of a working register (A,B,C and D)
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
W
S
M
X
 
A
 
XS
B
 
 

The field W:

 
It applies to all the four-bit bytes (64 bits), and thus extends from four-bit byte 0 to four-bit byte 15. This field is very useful when one wants to display an image with the screen quickly, or to make a fast exchange between two storage areas.

 
The field S:

 It includes/understands only four-bit byte 15. It is used rather little.

 
The field M:

This field includes/understands only 12 four-bit bytes, and extends from four-bit byte 3 with the four-bit byte 14. It is used rather little.
 

Field X:

This field includes/understands only 3 four-bit bytes. It is very useful, in particular during a test of the keyboard, or during the activation of the buzzer. This field extends from four-bit byte 0 with four-bit byte 2.

 
Field XS:

Field XS is a portion of field X; who includes/understands only four-bit byte 2. It is used very little.

 
Field B:

The field B includes/understands 2 four-bit bytes which extend from four-bit byte 0 to the four-bit byte 1. It is very useful when meters are used, or displays of sprites. But it is primarily used to manage the characters.

 
Field A:

The field A includes/understands 5 four-bit bytes which extends from four-bit byte 0 to four-bit byte 4. It is the field more employed and by far, indeed, it is primarily used during the reading or the pointing of addresses in memory. An address is coded on 5 four-bit bytes.
 

The field P:

This field is worth a four-bit byte, which corresponds to the value of P.
 

Field WP:

This field is worth P four-bit bytes.
 
 

Attention not to confuse the fields A and B, 
with the registers of calculation A and B!!
 
What can one make with these working registers?

Assignment of a value
 

To charge a value in one with registers A or C

LC 01235
LA 14

It should be noted that one can charge only 16 four-bit bytes maximum, and that these numbers are hexadecimal numbers. (# 12d = # Ch).

Ex: LC 0123456789ABCDEF
 

Mnemonic
LA n
LC n
  
To put at zero the field of a working register

The field will have to be specified by 'fs'. The contents of the field of the register are replaced by 0. To put at 0 the whole of the register, it is necessary to specify the field W (16 four-bit bytes).

 
 
Mnemonic
A=0 fs
B=0 fs
C=0 fs
D=0 fs
  
To handle an insulated bit
 

One can arm (to light) or disarm (to extinguish) a bit (or pixel) of a working register, with instruction ABIT and CBIT. ABIT relates to register A, CBIT the register C.

Example:

ABIT=1 4 % One arms bit 4 of the register A
CBIT=0 6 % One disarms bit 6 of the register C

Only the first 16 bits can be changed.
 
 
Mnemonic
ABIT=0 n
ABIT=1 n
CBIT=0 n
CBIT=1 n
  
To carry out an exchange of the fields between 2 registers

You specify the fields concerned with this exchange with: 'fs'. to exchange the totality of two registers, it is necessary to employ the field W.

Example:

ABEX A % the contents of fields A of registers A and B are exchanged

 
 
Mnemonic
ABEX fs
BCEX fs
CAEX fs
DCEX fs
  
Copy between two registers

 
The copy of a field between 2 registers relates to only one of the two registers, contrary to the exchange, or the 2 registers are concerned. To copy the whole of a register towards another, should be employed the field W.

Example:

A=C A % field A of the register C is copied from field A of register A
 

The copy is always carried out line on the left.
 
 
Mnemonic
A=B fs
B=A fs
B=C fs
C=B fs
C=A fs
A=C fs
D=C fs
C=D fs
  
Operations of the registers of calculation

 
The registers of calculation A,B,C and D enable us to carry out simple operations, like additions, subtractions, logical operations like "&" and "!" logic.

 

Additions:
 

It is possible for us to add two registers between them and to add an unspecified value to a register.

Addition of the field of two registers
(the field will have to be specified by: 'fs')

Example:

A=A+C A % the fields A of registers A and C are added
                % the result is copied in field A of register A

 
 
Mnemonic
A=A+B fs
B=A+B fs
B=B+C fs
C=B+C fs
C=C+A fs
A=C+A fs
D=D+C fs
C=D+C fs
  
The mnemonic following ones make it possible to double (* 2) the values of the fields of the registers.
 
 
Mnemonic
A=A+A fs
B=B+B fs
C=C+C fs
D=D+D fs
  
Addition of a constant to a field of a register

 
It is possible for us to add a value ranging between 0 and 17 (0<n<17) to a field specified by 'fs' of a register.

Example:

A=A+16 A % One adds 16 to field A of register A

 
 
Mnemonic
A=A+n fs
B=B+n fs
C=C+n fs
D=D+n fs
  
Subtractions
 

 It is possible for us to withdraw two registers between them and to withdraw an unspecified value from a register.

Subtraction of the field of two registers
(the field will have to be specified by: 'fs')
Example:

A=A-C A % the fields A of registers A and C are withdrawn
               % the result is copied in field A of register A

 
 
Mnemonic
A=A-B fs
B=B-C fs
C=C-A fs
D=D-C fs
B=B-A fs
C=C-B fs
A=A-C fs
C=C-D fs
A=B-A fs
B=C-B fs
C=A-C fs
D=C-D fs
  
Subtraction of a constant to a field of a register

 

It is possible for us to withdraw a value ranging between 0 and 17 (0<n<17) from a field specified by 'fs' of a register.

Example:

A=A-16 A % One withdraws 16 from field A of register A

 
 
Mnemonic
A=A-n fs
B=B-n fs
C=C-n fs
D=D-n fs
 
 
Complement with 2
 
 
Mnemonic
A=-A fs
B=-B fs
C=-C fs
D=-D fs
  
Complement with 1

 

The complement with 1 is used to reverse the contents of a field of a register.

Example:

A=-A A % One reverses the value contained in field A of register A

 
 
Mnemonic
A=-A-1 fs
B=-B-1 fs
C=-C-1 fs
D=-D-1 fs
  
Logical operations:

 

"!" logic

 

Representation of "or" logic:

 
 
n1 n2 result
0 

0 

1 

1

0 

1 

0 

1

0 

1 

1 

1

  

One uses much this method known as of "or" logical when one displays a sprite by transparence. We will study this method later.

 
 
Mnemonic
A=A!B fs
B=B!C fs
C=C!A fs
D=D!C fs
B=A!B fs
C=B!C fs
A=C!A fs
C=D!C fs
  
"&" logic

 

Representation of "and" logic:

 
 
n1 n2 result
0 

0 

1 

1

0 

1 

0 

1

0 

0 

0 

1

  

One employment generally this method known as of "and" logical when one tests a key of the keyboard. We will study that later.

 
 
Mnemonics
A=A&B fs
B=B&C fs
C=C&A fs
D=D&C fs
B=A&B fs
C=B&C fs
A=C&A fs
C=D&C fs
  
Rotations and shifts

 

Shift of a four-bit byte to the right and to the left

 

One specifies the field concerned with: 'fs'.

Example:

ASL A % One shifts field A of register A of a four-bit byte towards the left
CSR W % One shifts the field W of the register C of a four-bit byte towards the right

 
 
Mnemonic
ASL fs
BSL fs
CSL fs
DSL fs
ASR fs
BSR fs
CSR fs
DSR fs
  
During a shift on the left, the four-bit byte on the left of the specified field is lost, the four-bit byte on the right becomes 0.

During a shift on the right, the four-bit byte on the right of the specified field is lost, the four-bit byte on the left becomes 0.

 

Rotation of a four-bit byte to the right or to the left

 

All the four-bit bytes are concerned with rotation.

 
 
Mnemonic
ASLC
BSLC
CSLC
DSLC
ASRC
BSRC
CSRC
DSRC
  
During a shift to the right, the four-bit byte on the right takes the place of the four-bit byte lost on the left.

During a shift on the left, the four-bit byte on the left takes the place of the four-bit byte lost on the right.

 

Shift of a bit towards the right

 

All the bits of the register are concerned.

Example:

ASRB % One shifts all the bits of register A towards the right

 
 
Mnemonic
ASRB
BSRB
CSRB
DSRB
  
During a shift to the right, the bit on the right disappears, the bit on the left becomes 0.

 

Shift of a bit towards the right limited to a field

 

One specifies the field concerned with: 'fs'.

 
 
Mnemonic
ASRB.F fs 

BSRB.F fs 

CSRB.F fs 

DSRB.F fs

  

Shift of a bit towards the left

 

There is not similar instruction to shift a bit towards the left, but one can employ the instruction: A=A+A CH to carry out this shift on the left.

Ex: C=C+C W

(one shifts all the bits of the register C towards the left)

 
 
Mnemonic
A=A+A fs 
B=B+B fs 
C=C+C fs 
D=D+D fs
  
Registers of backup:

 

There are 5 registers of backup which are respectively: R0,R1,R2,R3 and R4. These registers are identical and make it possible to save the contents of the working registers A and C.

 

Copy of a working register towards a register of backup

 

All the fields are concerned with this operation.

 
 
Mnemonic
R0=A 
R1=A 
R2=A 
R3=A 
R4=A 
R0=C 
R1=C 
R2=C 
R3=C 
R4=C
  

Copy of a register of backup towards a working register

 

All the fields are concerned with this operation.

 
 
Mnemonic
A=R0 
A=R1 
A=R2 
A=R3 
A=R4 
C=R0 
C=R1 
C=R2 
C=R3 
C=R4
  

Copy of a field of a working register towards a register of backup

 

This operation concerns that the field specified (fs) and does not have any effect on the other fields.

 
 
Mnemonic
R0=A.F fs 
R1=A.F fs 
R2=A.F fs 
R3=A.F fs 
R4=A.F fs 
R0=C.F fs 
R1=C.F fs 
R2=C.F fs 
R3=C.F fs 
R4=C.F fs
  

Copy of a field of a register of backup towards the field of a working register

 

This operation concerns that the field specified (CH) and does not have any effect on the other fields.

 
 
Mnemonic
A=R0.F fs 
A=R0.F fs 
A=R2.F fs 
A=R3.F fs 
A=R4.F fs 
C=R0.F fs 
C=R1.F fs 
C=R2.F fs 
C=R3.F fs 
C=R4.F fs
  

Exchange of the contents of a working register with the contents of a register of backup

 

This operation relates to all the fields.

 
 
Mnemonic
AR0EX 
AR1EX 
AR2EX 
AR3EX 
AR4EX 
CR0EX 
CR1EX 
CR2EX 
CR3EX 
CR4EX
  

It should be noted that the instruction: AR0EX is the same one as this one: R0AEX, which is practically not employed by programmers.

 

Exchange of a field of a working register with the same field of a register of backup

 

This operation relates to only the field specified by 'fs'.

 
 
Mnemonic
AR0EX.F fs 
AR1EX.F fs 
AR2EX.F fs 
AR3EX.F fs 
AR4EX.F fs 
CR0EX.F fs 
CR1EX.F fs 
CR2EX.F fs 
CR3EX.F fs 
CR4EX.F fs
  
Pointer registers

 

There are 2 identical registers called 'pointer' on HP48. They are: D0 and D1. These registers fulfill several major functions:

They are able to read from and write to memory, to exchange their information with the working registers: A and C, to move of a value ranging between 0 and 17 (0<n<17).

 

Pointing and reading at an address in memory

 

There are two methods to point to memory. The first consists of directly specifying the address, the second method consists of pointing on field A (A as addresses!) of a working register containing this address.

By specifying the address directly

 

One points in memory while pointing on an address noted on 2,4 or 5 four-bit bytes.

Ex: D0 = 8068D

(one points on the address of the screen)

One reads from memory by recopying the address pointed in register A or C.

Ex: A=DAT0 A

(field A of register A contains the address pointed by D0)

 
 
Mnemonic
A=DAT0 fs 
C=DAT0 fs 
A=DAT1 fs 
C=DAT1 fs
  

While pointing on a register containing the address

 

Field A of the register concerned will have to contain the address to which one wants to point.

Ex:

D0 = 8068D

A=DAT0 A

(field A of register A contains the address of the screen)

D1=A

(D1 points on the beginning of the screen, with the address contained in field A of the register A).

Note that 'n' corresponds to an address of 2,4 or 5 four-bit bytes.

 
 
Mnemonic Mnemonic
D0 = n 

D1 = n

D0=A 

D0=C 

D1=A 

D1=C

  

One reads from memory by recopying the data pointed by D1 in a working register.

Ex: A=DAT1 W

(the field W of register A contains the first 16 four-bit bytes of the screen).

 
 
Mnemonic
A=DAT0 fs 
C=DAT0 fs 
A=DAT1 fs 
C=DAT1 fs
  

One can also indicate to the place of the noted field: 'fs', the number of four-bit bytes which one wishes right.

Ex: A=DAT1 4

(one reads only the first 4 four-bit bytes).

 

Mnemonic
A=DAT0 N 
C=DAT0 N 
A=DAT1 N 
C=DAT1 N
  
Displacement to the left and to the right of a pointer

 

One can move a pointer register on the left or on the right of a value of n ranging between 0 and 17 (0<n<17). It is very useful to traverse a storage area, or to display given to the screen.

Example:

D1 = 8068D % One points at an unspecified address
D1=D1+ 16 % One moves of 16 four-bit bytes towards the right

 
 
Mnemonic
D0=D0+ n
D0=D0- n
D1=D1+ n
D1=D1- n
  
writing at an address in memory

 

One writes to memory by recopying the data of register A or C, with the address pointed by D0 or D1.

Example:

D0 = 8068D
A=DAT0 A
D0=A % One points on the beginning of the screen
LA 1234 % One charges an unspecified value in register A
DAT0=A A % One recopies this value with the address pointed by D0

 
 
Mnemonic
DAT0=A fs
DAT0=C fs
DAT1=A fs
DAT1=C fs
  
One can also indicate to the place of the noted field: 'fs', the number of four-bit bytes which one wishes to write.

Example:

 DAT1=A 6 % One writes only the first 6 four-bit bytes

 

Mnemonic
DAT0=A n
DAT1=A n
DAT0=C n
DAT1=C n
  
Exchange between pointer registers and working registers

 
It is possible to exchange the contents of a pointer register with the contents of a working register, if it is not that only field A is concerned.

Example:

AD0EX % One exchanges the contents of field A of register A
             % with the contents of the register D0

 
 
Mnemonic
AD0EX
AD1EX
CD0EX
CD1EX
  
Jumps and tests
 
Jumps
 

Normally, a program is carried out beginning with the end, but it is possible to upset this direction by carrying out jumps. There are several types of jumps, the short jumps (GOTO), the long jumps (GOLONG), the subprogram calls short (GOSUB) and the long subprogram calls (GOSUBL).

One carries out a jump in the following way:

GOTO label

* label

You can put any name at the place of: ' label' if it is not that you cannot use the same label twice. Instruction GOLONG is the same one as instruction GOTO, but has a greater range:

GOTO (# 800h four-bit bytes)

GOLONG (# 8000h four-bit bytes)

There is an instruction known as absolute: GOVLNG

After use of this instruction, the program begins again with the specified address. It is a jump known as: absolute. One often uses this instruction to leave a program:

Example:

GOVLNG 05143

 

Subroutines

 
One uses the subroutines using the instructions: GOSUB and GOSUBL. When a subroutine is used, the start address is saved for a possible return of subroutine, generally noted: RTN.

Summary:

% beginning of a program
GOSUB label1 % the address below is saved
                       % and program goes to the named subroutine: label1
                       % After a return of subroutine
                       % the program begins again with the address saved below
GOVLNG 05143 % End of the program

* label1 % Subroutine: label
RTN % One returns to the initial address: it is the return of subroutine

Attention, one can go only 6 levels of subroutines deep, which though is not so bad!

GOSUB (short call: # 800h)

GOSUBL (long call: # 8000h)

 

Tests

 
A test is nothing else but a comparison between 2 working registers. It is preceded by the sign: ?

Ex: ?A=B A 

There is in addition a bit called: Carry, which manages the tests. A test is either true, or false. If the test is true, then the bit Carry is armed (it is worth 1 then), if on the contrary the test is false, the bit Carry is disarmed (it is worth 0). This special bit is used for to us to manage the result of a test. Indeed, on the state of this bit depend the following instructions:

?A=0 A

GOYES label2

% If Carry = 1 (true test), one carries out a jump towards the specified label.

% If not one continuous the program.

In the same way:

?A=C A

GONC label2

% If Curry = 0 (false test), one carries out a jump towards the specified label.

% If not,  one continuous the program.

The bit Carry is automatically switched to 0 after such an instruction. One can compare two working registers, according to a field in particular:

Ex: ?A=B W 

(one compares the fields W of registers A and B)

One can test by superiority or inferiority:

Ex: ?A<C B 

Ex: ?B>C A 

One can test if the field of a register is null or not:

?A=0 M

One can also test the state of a bit:

?ABIT=1 3

?CBIT=0 6

(on the left: the state of the bit (0 or 1), on the right: the number of the bit (0 to 15)).

 

Here is the table of mnemonic principal (fs means field and n the number of the bit to be tested with 0£ n£ 16):

 
 

Comparison
Inferiorite/Superiority
Bits
?A=0 fs
?A¹ 0 fs
?A=B fs
?A¹ B fs
?B=0 fs
?B¹ 0 fs
?B=C fs
?B¹ C fs
?C=0 fs
?C¹ 0 fs
?C=A fs
?C¹ A fs
?D=0 fs
?D¹ 0 fs
?D=C fs
?D¹ C fs
?A<B fs
?A£ B fs
?B<C fs
?B£ C fs
?C<A fs
?C£ A fs
?D<C fs
?D£ C fs
?A>B fs
?A³ B fs
?B>C fs
?B£ C fs
?C>A fs
?C£ A fs
?D>C fs
?D£ C fs
?ABIT=0 n
?ABIT=1 n
?CBIT=0 n
?CBIT=1 n
 
 

BASIC CONCEPTS
 
Routines in read-only memory.
The routines are portions of programs in read-only memory which can be compared to subroutines. They are of an extreme utility for the programmer because they carry out spots which frequently return in a program of play. These routines are called by a simple GOSBVL xxxxx or GOVLNG xxxxx.
>Note that these routines can affect certain registers of calculations like A,B,C or D, it will be necessary to hold of it account during the development of a program.
 
 
Function: Backup of the registers
Address S/sx:0679b
Call:GOSBVL
Address G/gx:0679b
This routine is that employed at the beginning of all the programs out of assembler. It backs up the registers D0,D1,B(A) and D(A)
 
 
Function: Restoration of the registers
Address S/sx:067d2
Call:GOSBVL
Address G/gx:067d2
This routine supplements the preceding one. It restores the registers D0,D1,B(A) and D(A) for a return to the rpl of the program.
 
 
Function: Detection of a pressure on a key
Address S/sx:00e0b
Call:GOSBVL
Address G/gx:00e0b
After the execution of the routine, C(A) contains the value of input of the key if a key is pressed and 00000 if no key is pressed. Register OUT is put at # 1FFh.
 
 
Function: C=IN
Address S/sx:01160
Call:GOSBVL
Address G/gx:01160
Place the 3 four-bit bytes of the register IN in the 5 four-bit bytes of the register C.
 
 
Function: Screen On
Address S/sx:01b8f
Call:GOSBVL
Address G/gx:01b8f
This routine lights the screen.
After execution, the register D0 points to address # 100h.
 
 
Function: Screen Off
Address S/sx:01bbd
Call:GOSBVL
Address G/gx:01bbd
This routine extinguishes the screen.
After execution, the register D0 points to address # 100h.
 
 
Function: Conversion of Decimal into Hexadecimal of the register C
Address S/sx:0d62f
Call:GOSBVL
Address G/gx:0d62f
Converts the decimal number placed in C(W) into hexadecimal. After execution of the routine, A(W), B(W), C(W) will contain the converted numbers.
 
 
Function: Conversion of hexadecimal into Decimal of register A
Address S/sx:0db91
Call:GOSBVL
Address G/gx:0db91
Converts the hexadecimal number placed in A(W) into Decimal.
After execution of the routine, A(W), B(W), C(W) will contain
the converted numbers.
 
 
Function: Interruptions Off
Address S/sx:
Call:GOSBVL
Address G/gx:01115
The interruptions are prohibited (ST=0 15).
 
 
Function: Interruptions On
Address S/sx:
Call:GOSBVL
Address G/gx:010e5
Authorize interruptions (ST=1 15).
 
 
Function: Reset (ON C)
Address S/sx:
Call:GOSBVL
Address G/gx:01fbd
Carry out a hot restarting as that realizes by the double
support on the keys ONE and C.
 
 
Function:Try to Recover Memory (ON A F)
Address S/sx:
Call:GOSBVL
Address G/gx:015f0
Even effect that triple support on the keys ONE A and F.
 
 
Function: Beep (D and C)
Address S/sx:
Call:GOSBVL
Address G/gx:017a6
Even effect that BEEP.
Register C(A) must contain the duration in milliseconds and D(A) the frequency in Hz 
 
 
Function: Mem
Address S/sx:
Call:GOSBVL
Address G/gx:06806
Even effect that MEM.
After execution, C(A) contains the memory size available.
D0 and A(A) are modified.
 
 
Function: $0000... 00
Address S/sx:
Call:GOSBVL
Address G/gx:05b7d
Create a character string made up of C(A) four-bit bytes.
After execution of the routine, D0 points on the first character.
R0, C(A) and D1 are modified.
 
 
Function: Exit
Address S/sx:
Call:GOSBVL
Address G/gx:05143
The sourest manner to leave a program out of assembler.
 
 
Function: D0 = screen
Address S/sx:
Call:GOSBVL
Address G/gx:0ç31
After execution of the routine, D0 points on the address of the beginning
screen. A(A) corresponds to D0.
 
 
Function: ClrLCD
Address S/sx:
Call:GOSBVL
Address G/gx:01bff
Erase the screen and the menus.
Registers A(W), C(A), and D0 are modified.
 
Useful addresses of the read-write memory:
The read-write memory (or RAM I/O) of the inputs and outputs is very useful for the programmer wishing to modify certain parameters of the HP48. Indeed the programmer will have the possibility using these addresses of modifying the contrast of the screen, of lighting or of extinguishing certain indicators on top of the screen for example. The range of addresses used by RAM I/O being itself from the address #00100h to address # 0013Fh.
The technique consists of reading the data pointed to an address of RAM I/O using a pointer register such D0 or D1:
ex: D0 = xxxxx
Reading the data pointed using a working register such as A or C:
ex: A=DAT0 A (or C=DAT0 A)
Modifying the data read by arming or disarming the bits of register A or C:
ex: ABIT=0 2 (or CBIT=1 3)
Then to rewrite the data thus modified at the address specified in D0 or D1:
ex: DAT0=A A (or DAT0=C A)
For that it is necessary to have a perfect knowledge of each address of RAM I/O under penalty of losses of frequent data!
 
Here are presented the principal addresses of RAM I/O:
 
 
#00101 Bit nr. 0 to 4 Contrast of the screen
Contrast can take 32 values (either # 20h.) coded on 5 bits. To modify the values of these 5 bits returns has to modify the contrast of the screen. Useful when one wishes to modify contrast during a play.
 
 
#0010B Bit nr. 0 to 3 Lighting of the indicators
State of these 4 bits depends lighting on the indicators in top of the screen. Bit 0 lights the indicator < when it is armed, bit 1 >, bit 2 a and bit 3 the indicator of ringing.
 
 
#0010C Bit nr. 1&3 Lighting of the indicators
Bit 0 lights the indicator 'busy' when it is armed, bit 1 the indicator of transmission. Bit 3 authorizes the lighting of the indicators when it is armed, or the interdicts when it is disarmed. Useful when one wishes to extinguish the occupied indicator.
 
 
#00120 Bit nr. 0 to 3 Address screen
The address of the GROB permanently displayed with the screen is fixed at this address. You can write a new address in #00120h to modify the grob screen.
 
 
#00128 Bit nr. 0 to 3 Small sweeping and height
These 4 bits control reading, the number of the lines being refreshed, in writing, the height of the menus. (by writing #3Fh in #00128h one makes disappear the bar from the menus). To obtain the number of the lines being refreshed, one reads the 6 bits (ex: D0 = 00128 A=DAT0 6). Register A is worth thus 0 when the last line was refreshed. The screen is refreshed 64 times a second. Useful for the development of a game in several levels of gray.
 
 
#00130 Bit nr. 0 to 3 Address bitmap finely
The screen is separated into two. The address of the lower part is fixed in #00130 and corresponds to the bitmap of the bar of the menus.
 
 
 
What is a source program?
 
The technical aspect having been approached, let us pass to the programming to be strictly accurate. To carry out a program in any language that it either requires the development with the precondition of a file known as: 'source'. Any program is initially a source file. It is thus represented by the HP by a chain: " ", and must imperatively end in the special character: @. What gives, for a program reduced to its simpler expression:
"
@ "
One obtains the character special: "@" by successive pressure of the keys: [ alpha ] [ green shift ] [ ENTER ].
 
How to make it executable?
 
We saw previously that a simple source program was summarized with:
"
@ "
If you assemble this source program, you will obtain your first executable Code then! But which will not carry out anything of course, because there is nothing in the program yet! One obtains then in the pile of the HP48:
 
 
 
 
 
Couples OUT/IN:
 
It thus proves essential to know the code of input and output of each keys:
 
 
out: 002 
in: 010
B 
out: 100 
in: 010
C 
out: 100 
in: 008
D 
out: 100 
in: 004
E 
out: 100 
in: 002
F 
out: 100 
in: 001
MTH 
out: 004 
in: 010
PRG 
out: 080 
in: 010
CST 
out: 080 
in: 008
VAR 
out: 080 
in: 004
­  
out: 080 
in: 002
NXT 
out: 080 
in: 001
' 
out: 001 
in: 010
STO 
out: 040 
in: 010
EVAL 
out: 040 
in: 008
¬  
out: 040 
in: 004
¯  
out: 040 
in: 002
®  
out: 040 
in: 001
SIN 
out: 008 
in: 010
COS 
out: 020 
in: 010
TAN 
out: 020 
in: 008
Ö X 
out: 020 
in: 004
yx 
out: 020 
in: 002
1/x 
out: 020 
in: 001
ENTER 
out: 010 
in: 010
+ / - 
out: 010 
in: 008
EEX 
out: 010 
in: 004
LED 
out: 010 
in: 002
Ü  
out: 010 
in: 001
a 
out: 008 
in: 020
7 
out: 008 
in: 008
8 
out: 008 
in: 004
9 
out: 008 
in: 002
¸  
out: 008 
in: 001
< 
out: 004 
in: 020
4 
out: 004 
in: 008
5 
out: 004 
in: 004
6 
out: 004 
in: 002
´  
out: 004 
in: 001
> 
out: 002 
in: 020
1 
out: 002 
in: 008
2 
out: 002 
in: 004
3 
out: 002 
in: 002
- 
out: 002 
in: 001
ONE 
out: 400 
in: 8000
0 
out: 001 
in: 008
. 
out: 001 
in: 004
SPC 
out: 001 
in: 002
+ 
out: 001 
in: 001
 
Important remarks:
 
The instruction: GOSBVL 01EEC replaces: OUT=C followed by GOSBVL 01160.
We can simply test the state of the bits in C(X), without using the code IN key to be tested:
Test of the key [ ENTER ]:
 
 
LC 010 
GOSBVL 01EEC 
?CBIT=1 4
Couples OUT of [ ENTER ] 
OUT=C GOSBVL 01160 
It is key actuated?  
 
To know of which bit one must test according to the key, if the key is keyboard on the right, it is bit 0. If it is a little on the right, bit 1,2,3,4. Of right-hand side on the left:
 
 
bit n:
bit n:
bit n:
bit n:
bit n:
4
3
2
1
0
 
The key [ ENTER ] is all on the left. This is why one with tested bit n: 4. This method of testing keys in assembler is the best, because it's the simplest the and smallest one.
 
Skeleton of a game:
 
Now that the tests of the keyboard were approached, we can set up the skeleton of a game. We thus will carry out a program which will end at the time of the support on a key of the keyboard. For that, we will take again the basic structure of a play studied previously, but first of all a warning:
ANY program whatever it is must ALWAYS begin with the routine:
 
 
GOSBVL 0679B
 
The purpose is to back up the current registers of Hp48. Then INTOFF which prohibits the processing of the keyboard.
The same ANY program must end in the routine:
 
 
GOSBVL 067D2 
A=DAT0 A 
D0=D0+ 5 
PC=(A)
 
Who restores the current registers of the HP48. But we will employ the more powerful routine rather to leave:
 
GOVLNG 05143
 
Thus, your first autonomous program will arise in the form:
 
" GOSBVL 0679B 
INTOFF 
% here is your program!! 
GOSBVL 05143 
@ "
 
It would be enough to assemble this mini source to realize that this program functions with wonder! Indeed, it launches out then stops automatically: It is magic you would say to me.
No, it is simply the ASSEMBLER !
 
Working
 
But let us return rather to our small game. The key to be tested will be ENTER. Let us analyze specific couple OUT/IN of key ENTER:
OUT: 010
One tests the state of bit nr.: 4 because the key is placed on the fourth column on the basis of the line.
The test specific to this key will be thus:
 
 
LC 010 
GOSBVL 01EEC 
?CBIT=1 4
Couples OUT of [ ENTER ] 
OUT=C GOSBVL 01160 
It is key actuated? 
 
 
 
Let us add that at a beginning and an end of our program:
 
 
GOSBVL 0679B 
INTOFF 
* loop 
LC 010 
GOSBVL 01EEC 
?CBIT=1 4 
GOYES label_2 
GOTO loop 
* label_2 
GOVLNG 05143
 
It is important to announce here that, in assembler, the programmer has multiple possibilities to carry out the same spot in a program. This is why certain programmers of games are very gifted HP48 parasites, in fact they are only very ordered and effective in the analysis of each function of their game. Thus, a programmer gains with clear and being structured in the development of his games.
But rather let us take again our small program, nothing does not prevent us from placing the test of key ENTER in subroutine. One gains then in clearness:
 
 
GOSBVL 0679B 
INTOFF
Principal core
* loop 
GOSUBL test_quit 
%coor of the code! 
GOTO loop
Subroutines
* test_quit 
LC 010 
GOSBVL 01EEC 
?CBIT=0 4 
RTNYES
End of the program
GOVLNG 05143
 
As their name indicates it, the subroutines will have to be always located at the end of the program. For those which one followed, nothing prevents from adding subprogram calls in the core of the game, then to write these subroutines ones following the others! One gains then in clearness and effectiveness. Each program with its method, however I think that this one is simplest with debugger : -)
Involve you to test other keys by modifying couple OUT according to the preceding table, as well as the state of the corresponding bits. It should be noted that if your machine does not answer any more, you will be able constantly to stop the procedure by the double support on the keys: ON_C What will cause immediate reset of HP48.
 
How to carry out a sound?
 
A video game is nothing different but a renewal of graphs, of some tests of the keyboard, the decorated whole of some sounds. We thus will study the manner of carrying out sounds. But be wary, you not to wait especially to hear your HP48 playing the Mozart or to recreate the environment of a play Mystique! In fact, the buzzer which equips the models of HP48 is very limited. It can play only some acute frequencies, not making it possible to carry out a tape sound. We will thus be satisfied to carry out simple sound effects, like the sound of the rebound of a ball against a wall for example!
To carry out a sound, several methods open with us.
We can do is :
- to have resorts to the routine BEEP which takes as argument the frequency and the duration of the sound.
- To even create the our own subroutine.
With an aim of familiarizing you with the assembly language, the second method proves to be preferable!
 
Let us proceed by stage successive:
 
* A sound is characterized by its frequency in Hertz and its duration in seconds.
* It is obtained while activating, then by decontaminating buzzer HP48, more or less quickly (the frequency), more or less a long time (duration).
Let us see how to make buzzer of HP48 to vibrate:
 
The buzzer is activated while placing #800h in register OUT, and it is decontaminated while placing #000h in this same register. An activation, followed by a desactivation causes a CLIC:
 
LC 800 
OUT=C 
C=0 X 
OUT=C
 
This support of program causes a CLIC. A continuation of clic at regular frequency causes a sound. Let us see how to carry out a frequency: We should place this program in a first loop, or register A(A) will be the meter. It will be the effective duration of the sound. We should place a second loop then, or B(A) will be the meter. It will be the effective frequency of the sound.
It is enough for us more whereas has to end a beginning and with our program to make it autonomous.
 
 
" 
GOSBVL 0679B 
INTOFF 
01000 
LC 00020 
B=C A 
D=C A 
* label_1 
LC 800 
OUT=C 
C=0 X 
OUT=C 
* label_2 
B=B-1 A 
GONC label_2 
C=D A 
B=C A 
A=A-1 A 
GONC label_1 
GOVLNG 05143 
@ "
 
To modify the initial value of register B(A) or A(A) thus amounts modifying the frequency or the duration of the sound thus emitted.
Assemble this program and listen to your HP which produces its first cry out of assembler!!
 
How to display a GROB?
 
We arrive now at the greatest part but also most delicate during the creation of a video game, namely: how to display a GROB of unspecified size to the screen? First of all, a small speech: The screen is a peripheral of the HP as well as the keyboard. It is in fact the representation of a portion of the memory, therefore to write on the screen amounts writing in memory. For that, the programmer will have resorts to the address of the beginning of the grob of the screen, located in memory, with the address: #8068Dh for the GX and #7050Eh for the SX.
 
The technique thus consists of pointing at this address using one of the pointer registers such D0 or D1, ex: D0 = 8068D of reading the address thus pointed, ex: A=DAT0 A, then to point on this address has new using D0 or D1, ex: D0=A One collects the data themselves using one of the working registers such A(A) or C(A), by a reading of the zone thus pointed, ex: A=DAT0 A (Field A indicates that one wants to modify the first 5 four-bit bytes, that is to say 5 * 4 = 20 pixels). One can thus modify with wish these data: ex: A=0 A (one erases) or ABIT=1 3 (bit 3 is armed) and one rewrites given thus modified, ex: DAT0=A A
 
D0 = 8068D %(address of the screen)
A=DAT0 A %(lecture of the address)
D0=A %(point at this address)
A=DAT0 W %(reads the 16 four-bit bytes, that is to say 16 * 4 = 64 pixels)
ABIT=1 4 %(arm pixel 4)
DAT0=A A %(rewrites the data thus modified)
 
If one wants, one can even charge a value and display it with the screen, ex: LC 55 DAT0=C B (# 55h corresponds to # 0101010101b) It will then be displayed with the screen value # 55h, or rather bits 1010101010 of the screen.
 
It will then be enough for us to traverse the totality (or a part) of the screen to display a GROB on all the screen (or a part). One course data of the screen while making moving the register to point ahead:
ex: D0=D0+ n (0<n<17)
or D1=D1+ n (0<n<17)
or behind if one is located in bottom of the screen,
ex: D0=D0- n (0<n<17)
or D1=D1- n (0<n<17)
When you move the register ahead to point, you move left then on the right. When you exceed the screen (on the right), the register points then on the left, a lower line.
You traversed a line of the screen (136 pixels), after having incremented your register to point of 34 four-bit bytes ahead, or behind. Indeed, 34 * 4 = 136 pixels!
Caution: #34d = > #22h
What gives with the register to point D0:
D0=D0+ 16
D0=D0+ 16
D0=D0+ 2
Or:
D0=D0- 16
D0=D0- 16
D0=D0- 2
Another more effective method would be to exchange the contents of the pointer with that of a working register, to modify this working register and finally, to exchange the contents of the working register in question with the pointer. Ex:
D0 = 8068D
A=DAT0 A
D0=A %(D0 points with the screen)
AD0EX %(place the address of D0 in A(A))
LC 00022 %(load #22h is #34d four-bit bytes, a line)
A=A+C A %(moves of a line downwards)
AD0EX %(replaces the new address in D0)
Summary:
To modify a data with the screen:
D0 = 8068D
A=DAT0 A
D0=A % One points on the beginning of the screen
A=DAT0 W % One recovers in A(W) the data of the screen: 16 four-bit bytes 64bits
A=0 W %(on erases) or ABIT=1 8 (one arms pixel 8)
DAT0=A W % One rewrites the data thus modified
to write a data with the screen:
By crushing:
D0 = 8068D
A=DAT0 A
D0=A % One points on the beginning of the screen
C=0 A
LC 55555 % Loading of a value in C(A)
DAT0=C A %On writes the data contained in C(A) over the current data
 
By transparency:
D0 = 8068D
A=DAT0 A
D0=A % One points on the beginning of the screen
A=DAT0 A % One reads the current data
C=0 A
LC 55555 % Loading of a value in C(A)
C=C&A A % " and " logic enters the current data and the data charged
DAT0=C A % One writes the data contained in C(A) by transparency
 
To display a GROB on all the screen
 
Above all, point out what is really a GROB. A GROB is a graphic object obtained using environment PICTURE of your HP48. In this object are stored all the data concerning the graph. It is thus by reading these data that one can then display a GROB with the screen.
Accustom you as of now handling the GROB:
 
In environment PICTURE, draw then back up your drawing using the key [ STO ].
Your drawing is then placed in the 1. level of the pile, that gives:
Grob 131 * 64
To be able to insert it in your source program, it is necessary to remove with the GROB their foreword and their size. For that, you must republish the GROB in the following way:
GROB 131 64 123454100 [... 000
Becomes then:
$1234541000 [... 000
By suppression of prologue GROB 131 64, useless in assembler.
To notice:
The insertion on the left of the character $ which characterizes, in a source program, an unspecified data.
Thus, your GROB must resemble this one:
$12345100015343154135411531435411654153411531..
For launching out in the display of a GROB on the whole screen, still is necessary it that you know how to recover the address of this GROB!
With this intention, there are several methods: the most known and employed of all the programmers out of assembler is this one:
Method 1
GOSUBL label_1 % One places the beginning of the GROB in RSTK
$000000032251405231430 % (it is the grob without its size)
* label_1
C=RSTK % Ici one recovers in C(A) the address of the GROB
              % A the output, C(A) contains the address of the beginning of the GROB
              % One can then is to save this address, (in R0 for example)
              % is to point directly on this one using one of the registers
              % pointer D0 or D1.
Example:
D0=c % Or D1=c
Method 2
The second method consists in directly reading a GROB in the pile, and to display it with the screen. For that, one needs from the very start of the program the address which contains the register D1, because usually, it is in this register that is the address of the object contained in the first level of the pile. One reads this address using the instruction:
A=DAT1 A % Or C=DAT1 A
If this address is worth 0, therefore if A(A) is null, there are no objects in the pile.
One tests then with:
?A¹ 0 A
GOYES label_1
GOVLNG 05143
* label_1
this level, one could test if the object in the pile is well a graphic object:
LC 02B1E
?A=C A
GOYES label_2
GOVLNG 05143
* label_2
It remains us more than has to point on this GROB using the instruction:
D1=A
This stage, it remains more than has to carry out the copy of the data of the GROB on the data of the screen. Here is the complete program which displays a GROB of 131 * 56 on the screen:
 
 
" GOSBVL 0679B 
INTOFF 
GOSUBL label_1 
$123454115341865346854186 [...  
* label_1 
C=RSTK 
D1=C 
%(D1 points on the GROB to display) 
D0 = 8068D 
A=DAT0 A 
D0=A 
%(D0 points on the beginning of the screen) 
LC 76F 
%(has 56 lines there to display: 56 * 136 = %7616 pixels, is 1904 four-bit bytes, or %encore # 770h. #770 - 1 = # 76Fh.) 
* label_2 
A=DAT1 A 
%(recopy the data of the GROB %pointée by the pointer register D1, %dans A(A)) 
DAT0=A 1 
%(copy four-bit bytes by one, the %GROB with the screen, the address contained %dans the pointer register D0) 
D0=D0+ 1 
%(moves of a four-bit byte on the right %sur the screen) 
D1=D1+ 1 
%(moves of a four-bit byte on the right %sur the GROB) 
C=C-1 X 
GONC label_2  
%(loop ends when #770h %quartet is copied to the screen. That is to say a %GROB of 131 * 56 pixels) 
GOVLNG 05143 
@ "
 
Nothing prevents us from recopying the data of the GROB to the screen, by several four-bit bytes at the same time.
It is then enough to use larger fields (ex: fields B,X,W)
in the following way:
A=DAT1 B
DAT0=A B
Here, the fields B gathers 2 four-bit bytes, the display will be carried out 2 times more quickly, in the condition of adjusting the meter of loop:
(#770h ¸ 2) -1 = #3B7h
If not, the loop is too long and one writes in the read-write memory (after the last line of the screen), which is formally interdict under penalty of Mémory-lost!
Same manner, if one uses the fields W (16 four-bit bytes), one thus needs a loop of value: (#770h ¸ #10h) - 1 = #76h
Thus, it is by as well as possible adjusting the fields of our registers, during the display of one GROB to the screen, which one can gain much speed of execution of the play.
But this method is valid only for the display of GROB of 131 pixels of width, if not it is necessary to operate in a different way.
 
To manage the sprites
How to display a sprite?
First of all, it should be announced that out of assembler your sprites must have a width which amounts in four-bit bytes, by group of 4 pixels. I.e.: 4, 8, 12, 16, 20, 24... for a simple reason: that corresponds to the size of the fields of the registers of works! Thus, for a sprite of 8 * 12 pixels, one will employ the fields B to display a line of this sprite because the fields B can contain 8 pixels. You will have to hold account of it when you carry out your sprites!
The sprites are drawn in surround PICTURE of your HP48.
To recover a portion of screen (a ball for example) of environment PICTURE, place the cursor in top on the left of this sprite and press on the key [ * ] to place a mark, to then move you in bottom on the right of this sprite and actuate the command [ sub ] to extract your sprite. This sprite is then placed in the pile. Let us take the example of a sprite of 8 * 12 pixels, Dessinez a black rectangle of size 8 * 12 pixels, then extract gives it, that in the pile:
Grob 8 * 12
If you publish it:
GROB 8 12 FFFFFFFFFFFF
Then remove the prologue and add the character $:
$$FFFFFFFFFFFF
It is this portion of graph or sprite which we must display with the screen. The width being equal to 8 pixels, we will employ the fields B louse to carry out the display.
With this intention, several methods.
By crushing
We will employ again the method here said " by crushing ", already approached previously. That means that the sprite will be displayed over the current data of the screen.
To display a sprite, it is first of all necessary to take account of its size. Here the width of our sprite is equal to 8 pixels, we will thus employ the fields B which is adapted best to the situation. The technique then consists in displaying the sprite line with line, and this using a loop which corresponds to the height (-1) in pixels of the sprite. Here, our sprite with an effective height of 12 pixels, is # CH - 1 = # Bh. Our loop of display will have like initial value: # Bh.
to pass from one line to the following one:
With the screen that corresponds has a shift of 34 quads (# 22h), on the other hand, on the sprite, all depends on its width. For a width of 4 pixels, one moves of two four-bit bytes:
 
 
0>4 pixels:
4>8 pixels:
8>12 pixels:
12>16 pixels:
16>20 pixels:
20>24 pixels:
24>28 pixels:
...
2 four-bit bytes
2 four-bit bytes
4 four-bit bytes
4 four-bit bytes
6 four-bit bytes
6 four-bit bytes
8 four-bit bytes
...
 
 
Here the width of the sprite to be displayed being equal to 8 pixels, one will move line on line: 2 four-bit bytes by 2. We will display our sprite starting from the left higher corner of the screen by recovering the address in: GOSBVL 0Ç31. Here what that gives:
 
 
" GOSBVL 0679B 
INTOFF 
GOSUBL sprite_1 
$$FFFFFFFFFFFF 
* sprite_1 
C=RSTK 
%(on recovers the address of the sprite) 
D1=C %(D1 points on the sprite) 
GOSBVL 0Ç31 
%avec this routine D0 points on the screen 
P = 0 
LC B %(il has 12 there line, 12-1=11 or # Bh) 
* label_1 
A=DAT1 B %(on reads the sprite) 
DAT0=A B %(on recopies it on the screen) 
D0=D0+ 16 
D0=D0+ 16 
D0=D0+ 2 
%(on passes to the following line to the screen) 
D1=D1+ 2 
%(on passes to the following line sprite) 
C=C-1 P 
GONC label_1 
%(c' is the loop, 12 line to be copied) 
GOVLNG 05143 
%(on leaves the program!) 
@ "
 
 
By transparency
This technique of display having already been approached previously, we will not be delayed there. Know that the technique called by transparency consists has to copy the sprite with the screen over the data of the screen by transparency between the screen and the sprite. For that, one will use the instruction '! ' called: " and " logic. The fields B will play the part of the meter of loop. Here our program:
 
 
" GOSBVL 0679B 
INTOFF 
GOSUBL sprite_1 
$$FFFFFFFFFFFF 
* sprite_1 
C=RSTK %(on recovers the address of the sprite) 
D1=C %(D1 points on the sprite) 
GOSBVL 0Ç31 
%(avec this routine, D0 points on the screen) 
P = 0 
LC B %(il has 12 there line, 12-1=11 or # Bh) 
B=C P 
* label_1 
A=DAT1 P %(on reads the sprite) 
C=DAT0 P %(on reads the screen) 
A=A!C P %(on ' mélange' the whole!) 
DAT0=A P %(on recopy on the screen) 
D0=D0+ 16 
D0=D0+ 16 
D0=D0+ 2 
%(on passes to the following line to the screen) 
D1=D1+ 2 
%(on passes to the following line sprite) 
B=B-1 P 
GONC label_1 
%(c' is the loop, 12 line to be copied) 
GOVLNG 05143 %(on leaves the program!) 
@ "
 
One cannot work out a video game without knowing to manage the sprites perfectly. Thus it is necessary that you have a perfect command of this part of the chapter. Involve to handle the GROB, sprites and others.
 
How to move a sprite?
 
First approach:
 
To move a sprite amounts moving on the screen its position of display. This position depends on the address on which one points with the screen. To modify this address amounts modifying the position of display of the sprite, and thus to move it. For that, it is necessary to the precondition to carry out a backup of the address or the sprite must be displayed. One could as an example save this address in the register of backup R0. That will give us then:
GOSBVL 0Ç31
AD0EX
R0=A
It will be enough for us then to move the sprite to add 1 A the address backed up in R0:
A=R0
A=A+1 A
R0=A
Our sprite will move then four-bit byte (4 pixels) on the right. Conversely, to move the sprite of a four-bit byte on the left:
A=R0
A=A-1 A
R0=A
To downwards move the sprite of a line of the screen, it is necessary to add 34 (# 22h) at this address:
A=R0
A=A+16 A
A=A+16 A
A=A+2 A
R0=A
Conversely, one upwards moves our sprite of a line of the screen by withdrawing 34 at this address:
A=R0
A=A-16 A
A=A-16 A
A=A-2 A
R0=A
 
 
Display sprites (pixel by pixel)
(D.B = n lines of the sprite; A.A=X;  C.A=Y; D1=@grob; D0=@screen)
Authors: HPmad, HPandy, SunHP
C=C+C.A B=C.A CSL.A B=B+C.A CD0EX C=C+B.A B=A.A ASRB.A ASRB.A D0=C 
DO { A=B.A C=DAT1.A ?ABIT=1.0 { C=C+C.X } ?ABIT=1.1 { C=C+C.X C=C+C.X } 
A=DAT0.A A=-A-1.A C=DAT1.4 A=A&C.A DAT0=A.4 D1=D1+ 4 D0=D0+ 34 D--.B 
} WHILENC
 
 

 Although very incomplete, I hope sincerely that of the world of the programming out of assembler on HP48G(X) you will have liked this small approach!!To further go, it will be necessary for you Hp48gX with a card of 128Kb + a ML48 book.
 
Document translated by Tomas Furlan.
 
Julien Meyer
Back to my Home Page