Jump to content
Jet Set Willy & Manic Miner Community

Free space and code optimisation in "JSW"


jetsetdanny

Recommended Posts

This is a re-use of the same algorithm. This time it translates a key press into a key value. Could be used for high score input which uses the keyboard to type in a name and not the easy scroll letters to get an input. The big wastage is the translate table. The purpose of typing this is only to show a quick re purposing of a routine. (Of note I have seen far worse than this)
.
.
key_input:
LD HL,TABLE-1

LD BC,#FEFE

 

keyloop1:

IN A,( C )

LD E,5

keyloop2:

INC HL

RRCA

JR NC,key_pressed

DEC E

JR NZ,keyloop2

RLC B

JR NC,keyloop1
JR C,keyloop1   << corrected

JR key_input

 

 

key_pressed:

LD A,(HL)                 ;the key value from the keyboard

.

.

TABLE  db   0,"ZXCVASDFGQWERT1234509876POIUY",13,"IJKL ",1,MNB"
TABLE db    0,"ZXCVASDFGQWERT1234509876POIUY",13,"LKJH ",1,"MNB"  <<hopefully corrected
 

 

shift translates as 0, symbol shift as 1, enter as 13

 

Edited to correct the errors from my quick transcribe. 

Edited by Norman Sword
Link to comment
Share on other sites

  • 2 months later...

I've found a six nine-byte saving in the 'Initialise the title screen' routine, by replacing the individual checks of various attribute values at #8844-#8870, inserting a couple of look-up tables and using two CPIR commands.

 

I'll type up a disassembly when I find the time.  :)

Edited by IRF
Link to comment
Share on other sites

There follows a disassembly of my rewrite of the Impossible Triangle-drawing code, as mentioned in my previous post.  The rewritten part of the routine now saves eight bytes, compared with the original.

 

N.B. I believe that this is exactly the sort of thing that the CPIR command should be used for (unlike Matthew's dodgy application of CPIR in the room-drawing code, which gives rise to the Cell Graphics Bug).

 

 

Title_screen_data           EQU    #885D       ; A new data table, which contains all the attribute values which were individually checked

                                                                     ; via CP #nn commands in the original code (and the former operand of a LD A, #nn command)

Triangle_graphic_data    EQU    #8431       ; The original table containing the pixel-graphics used to create the impossible triangle.

                                                                     ; There are two halves to this table (at #8431 and #8441), and each half contains a pair

                                                                     ; of two eight-byte graphics (e.g. graphics start at #8431 and #8439 for the first half of the table)

 

ORG: #8841

LD DE, #5800

 

Impossible_triangle_loop:

LD A, (DE)

LD HL, Title_screen_data            ; HL now points at the start of the data table, in preparation for the CPIR loops (and other commands) that follow

LD BC, #0005                              ; BC counts down the CPIR loop, but B is also used to indicate which half of the graphic data at #8431 is picked up

CPIR                                            ; Search through the first five entries in the data table 

JR Z, Nothing_to_draw                ; If there is a match, then this particular screen cell contains no pixel-graphics

 

LD C, #03                                    ; B still holds 00 at this point (and HL is pointing at the next part of the data table)

CPIR                                            ; Search through the next three entries in the data table

JR Z, Draw_triangle_segment     ; If there is a match, then draw a part of the triangle using the first half of the graphic data at #8431

 

CP (HL)                                       ; Check A against the penultimate value in the data table...

INC HL                                         ; ...and move HL on to the final entry in the table (I tried a CPI command here, but that doesn't preserve B = #00)

JR Z, switch_INK_and_PAPER   ; If there is a match with the penultimate entry, then we are at the 'tricky corner' of the triangle

 

LD B, #10                                    ; No match in the data table, so we need to select a graphic from the second half of the pixel data

JR Draw_triangle_segment         ' (i.e. the parts of the triangle which slope 'up-to-the-right')

 
Title_screen_data:                    ; This table could be moved elsewhere in the code, but every path through this routine jumps past it,
                                                  ; so it can safely be left here
DEFB #00 #09 #24 #2D #D3    ; These entries correspond to parts of the screen with no pixel-graphics (i.e. the black background, flashing lettering, 
                                                  ; or solid parts of the triangle which have matching INK and PAPER colours)
DEFB #05 #08 #29            ; All remaining entries in the table correspond to parts of the triangle which slope 'down-to-the-right'
DEFB #2C #25              ; If the attribute in the cell under consideration is #2C (green INK/cyan PAPER), then replace it with #25 (cyan INK/green PAPER)
 
; N.B. I could have save an extra byte by retaining the original commands for the last two entries [CP #2C and LD A, #25 / LD (DE), A],
; and omitting the last two entries in the table, but I considered it more elegant to have all the data stored within a single data table
 
DEFS #08                                  ; Eight unused bytes (NOPs) - the point of the exercise!  (These can obviously be consolidated elsewhere)

 

Switch_INK_and_PAPER:

LD A, (HL)                                    ; Pick up the final entry in the data table and update the attribute in this cell (this swaps the INK/PAPER colours around...

LD (DE), A                                    ; ... which allows the green/cyan corner of the triangle to be drawn using all four of the graphics at #8431)

 

; N.B. From hereon in, there are further byte-efficiencies to be achieved, which are documented earlier in this thread,

; but which I haven't (yet) incorporated below

 

Draw_triangle_segment:

LD A, E

AND #01                                      ; Whether E has an even or odd value determines which half of the selected pair of graphics from #8431 is used

RLCA

RLCA

RLCA

OR B                                            ; Determines which pair of graphics from #8431 is used (N.B. this has been changed from the OR C in the original code)

LD C, A

LD B, #00

LD HL, Triangle_graphic_data

ADD HL, BC

PUSH DE

BIT 0, D

LD D, #40

JR Z, correct_part_of_screen_identified

LD D, #48

Correct_part_of_screen_identified:

LD B, #08

CALL #969B

POP DE

 

Nothing_to_draw:

INC DE

LD A, D

CP #5A

JP NZ, Impossible_triangle_loop

 

 

EDIT: I should also mention that the above rewrite still works if the erroneous attribute in the original title screen is corrected (i.e. the green/black cell inside the lower part of the letter 'S', which should properly be green and blue).

This can be fixed by editing the data at source, within page #98 (i.e. POKE #98D2, #0C) - no change to the new table at #885D is required, because the corresponding triangle segment slopes down-to-the-left, and so it doesn't need a specific entry in the table (the correct graphic is selected 'by default').

Edited by IRF
Link to comment
Share on other sites

I did wonder a while back if there was a better way of doing this, not the actual code more the way the 'data' for it is present. I vaguely recall trying a fully compressed full screen to expand and LDIR into screen memory although from what I remember there were no byte savings from this, given it had to live 'somewhere' anyway in its original format.

 

Impressive stuff. :thumbsup:

Link to comment
Share on other sites

I'm aware that there are large areas of the title screen with many consecutive identical attribute values (e.g. the first two character rows all hold 00), where it is much more efficient to use a few simple loops to write the appropriate values to the 'uniform' parts of the screen, instead of storing whole chunks of repetitive data (e.g. 64 consecutive 00 bytes for the top two rows) and copying the whole screen using a single LDIR command (as was the case in the original code).

 

EDIT: That is to say, the amount of bytes saved in optimising the storage of the Title Screen's attribute data, vastly outweighs the modest saving which I have just come up with for the routine that draws the Impossible Triangle's pixels based on the attribute data.

Edited by IRF
Link to comment
Share on other sites

  • 3 months later...

Small rewrite in the JSW game initialisation code which saves a byte:

 

87F5   LD HL,$857C     87F8   LD (HL),$30     87FA   INC HL     87FB   LD (HL),$30     87FD   INC HL     87FE   LD (HL),$30

 

LD HL, #857C

LD BC, #0330

loop:

LD (HL), C

INC HL

DJNZ loop

Edited by IRF
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.