Prev: C352 Up: Map Next: C463
C356: Draw Picture: Unpack
Used by the routine at DrawPicture.
Continues from DrawPicture.
Find out where this code is in memory. The call leaves its return address (DrawPicture_ReturnAddress) just below the stack pointer. An interrupt at this point would overwrite it, so BASIC calls DisableInterrupts first and EnableInterrupts afterwards.
DrawPicture_Unpack C356 CALL $007C Call the RET instruction at 007C, at the end of CH_ADD+1, which returns straight away.
DrawPicture_ReturnAddress C359 DEC SP Move the stack pointer back down to the return address.
C35A DEC SP
C35B EX (SP),HL Swap it into HL, so HL=DrawPicture_ReturnAddress.
C35C INC SP Move the stack pointer back up again.
C35D INC SP
C35E AND A Clear the carry flag ready for the subtraction.
C35F LD DE,$0007 HL=DrawPicture_Number (DrawPicture_ReturnAddress less 0007).
C362 SBC HL,DE
C364 PUSH HL Stash the address of the parameters on the stack.
C365 POP IY Restore the address of the parameters from the stack into IY.
C367 LD DE,$012A HL=Graphics_DepartmentOfNationalPolice (DrawPicture_Number plus 012A), the first picture record.
C36A ADD HL,DE
C36B LD A,(IY+$00) A=the picture number from *DrawPicture_Number.
Skip over the records before the requested picture.
DrawPicture_FindPicture C36E DEC A Decrease the picture number by one.
C36F JR Z,DrawPicture_Found Jump to DrawPicture_Found if HL points to the requested picture.
C371 LD E,(HL) DE=the length of this record, less one.
C372 INC HL
C373 LD D,(HL)
C374 ADD HL,DE Add it to HL, so HL points to the next record.
C375 JR DrawPicture_FindPicture Jump to DrawPicture_FindPicture.
DrawPicture_Found C377 LD DE,$4000 DE=4000. This value is never used, as D and E are both set again before they are needed.
C37A INC HL Move HL past the length, to the record's screen third.
C37B INC HL
C37C LD A,(IY+$01) A=*DrawPicture_Third.
C37F INC A Increment A by one, so that FF becomes zero.
C380 JR NZ,DrawPicture_Unpack_0 Jump to DrawPicture_Unpack_0 if *DrawPicture_Third is not FF.
C382 LD A,(HL) Else write the record's screen third to *DrawPicture_Third.
C383 LD (IY+$01),A
DrawPicture_Unpack_0 C386 INC HL Move on to the record's number of thirds.
C387 LD A,(IY+$02) A=*DrawPicture_Thirds.
C38A INC A Increment A by one, so that FF becomes zero.
C38B JR NZ,DrawPicture_Unpack_1 Jump to DrawPicture_Unpack_1 if *DrawPicture_Thirds is not FF.
C38D LD A,(HL) Else write the record's number of thirds to *DrawPicture_Thirds.
C38E LD (IY+$02),A
DrawPicture_Unpack_1 C391 INC HL Move on to the record's flags.
C392 LD A,(HL) Copy the record's flags to *DrawPicture_Flags.
C393 LD (IY+$03),A
Make sure the picture fits on the screen.
C396 LD A,(IY+$01) A=*DrawPicture_Third.
C399 CP $03 Jump to DrawPicture_Unpack_2 if the screen third is less than 03.
C39B JR C,DrawPicture_Unpack_2
C39D LD (IY+$01),$00 Else start at the top third (write 00 to *DrawPicture_Third).
DrawPicture_Unpack_2 C3A1 LD A,(IY+$02) A=*DrawPicture_Thirds.
C3A4 CP $04 Jump to DrawPicture_Unpack_3 if the number of thirds is less than 04.
C3A6 JR C,DrawPicture_Unpack_3
C3A8 LD (IY+$02),$01 Else draw one third (write 01 to *DrawPicture_Thirds).
DrawPicture_Unpack_3 C3AC ADD A,(IY+$01) Add the screen third to A. A still holds the number of thirds read at DrawPicture_Unpack_2, even when it has just been changed.
C3AF CP $04 Jump to DrawPicture_Unpack_4 if the picture ends on the screen (the total is less than 04).
C3B1 JR C,DrawPicture_Unpack_4
C3B3 LD (IY+$02),$01 Else draw one third (write 01 to *DrawPicture_Thirds).
DrawPicture_Unpack_4 C3B7 LD A,(IY+$02) A=*DrawPicture_Thirds.
C3BA AND A Jump to DrawPicture_Pixels if the number of thirds is not zero.
C3BB JR NZ,DrawPicture_Pixels
C3BD LD (IY+$02),$01 Else draw one third (write 01 to *DrawPicture_Thirds).
Draw the pixels.
DrawPicture_Pixels C3C1 INC HL Move HL on to the start of the picture data.
C3C2 LD E,$00 E=00 (the left-hand column).
C3C4 LD A,(IY+$01) A=*DrawPicture_Third.
C3C7 ADD A,A Multiply it by 08 as each third of the screen is 08 pages long.
C3C8 ADD A,A
C3C9 ADD A,A
DrawPicture_PixelsHighByte C3CA ADD A,$40 Add the high byte of the start of the screen (40). BASIC POKEs this byte to draw into a buffer instead.
C3CC LD D,A Set D and C to the high byte of the top pixel line of the picture, so DE holds its screen address.
C3CD LD C,A
C3CE LD B,$01 B=01 (one pass, for row order).
C3D0 BIT 0,(IY+$03) Jump to DrawPicture_PassLoop if bit 0 of *DrawPicture_Flags is set (row order).
C3D4 JR NZ,DrawPicture_PassLoop
C3D6 LD B,$20 Else B=20 (one pass for each column).
DrawPicture_PassLoop C3D8 PUSH BC Stash the pass counter on the stack.
C3D9 LD B,(IY+$02) B=the number of thirds from *DrawPicture_Thirds.
DrawPicture_ThirdLoop C3DC PUSH BC Stash the thirds counter on the stack.
C3DD LD B,$08 B=08 (character rows in a third).
DrawPicture_RowLoop C3DF PUSH BC Stash the character row counter on the stack.
C3E0 LD B,$08 B=08 (pixel lines in a character row).
DrawPicture_LineLoop C3E2 PUSH BC Stash the pixel line counter on the stack.
C3E3 LD B,$01 B=01 (one byte, for column order).
C3E5 BIT 0,(IY+$03) Jump to DrawPicture_Unpack_5 if bit 0 of *DrawPicture_Flags is clear (column order).
C3E9 JR Z,DrawPicture_Unpack_5
C3EB LD B,$20 Else B=20 (a whole pixel line, for row order).
DrawPicture_Unpack_5 C3ED PUSH DE Stash the screen address of this pixel line on the stack.
DrawPicture_ByteLoop C3EE PUSH BC Stash the byte counter on the stack.
C3EF JR DrawPicture_FetchByte Jump to DrawPicture_FetchByte to write the next byte; it comes back to DrawPicture_NextByte.
DrawPicture_NextByte C3F1 POP BC Restore the byte counter from the stack.
C3F2 INC DE Move right to the next screen byte.
C3F3 DJNZ DrawPicture_ByteLoop Decrease the byte counter by one and loop back to DrawPicture_ByteLoop until it is zero.
C3F5 POP DE Restore the screen address of this pixel line from the stack.
C3F6 POP BC Restore the pixel line counter from the stack.
C3F7 INC D Move down to the next pixel line.
C3F8 DJNZ DrawPicture_LineLoop Decrease the pixel line counter by one and loop back to DrawPicture_LineLoop until all 08 pixel lines are done.
C3FA LD A,D Move D back up to the top pixel line of this character row (subtract 08).
C3FB SUB $08
C3FD LD D,A
C3FE LD A,E Move down to the next character row (add 20 to E).
C3FF ADD A,$20
C401 LD E,A
C402 POP BC Restore the character row counter from the stack.
C403 DJNZ DrawPicture_RowLoop Decrease the character row counter by one and loop back to DrawPicture_RowLoop until all 08 character rows are done.
C405 LD A,D Move down to the next third (add 08 to D). E has gone back round to the same column.
C406 ADD A,$08
C408 LD D,A
C409 POP BC Restore the thirds counter from the stack.
C40A DJNZ DrawPicture_ThirdLoop Decrease the thirds counter by one and loop back to DrawPicture_ThirdLoop until all the thirds are done.
C40C LD D,C Move D back up to the top of the picture (D=C).
C40D INC E Move right to the next column.
C40E POP BC Restore the pass counter from the stack.
C40F DJNZ DrawPicture_PassLoop Decrease the pass counter by one and loop back to DrawPicture_PassLoop until all the passes are done.
Draw the attributes.
DrawPicture_Attributes C411 LD E,$00 E=00.
DrawPicture_AttributesHighByte C413 LD A,$58 A=58 the high byte of the start of the attribute file. BASIC POKEs this byte to draw into a buffer instead.
C415 ADD A,(IY+$01) Add the screen third.
C418 LD D,A D=A, so DE holds the address of the first attribute of the picture.
C419 LD B,(IY+$02) BC=the number of attributes to draw: 256 for each third (B=*DrawPicture_Thirds and C=00).
C41C LD C,E
C41D SET 3,(IY+$03) Set bit 3 of *DrawPicture_Flags, so that DrawPicture_FetchByte comes back to DrawPicture_NextAttribute.
DrawPicture_AttributesLoop C421 PUSH BC Stash the attribute counter on the stack.
C422 JR DrawPicture_FetchByte Jump to DrawPicture_FetchByte to write the next attribute; it comes back to DrawPicture_NextAttribute.
DrawPicture_NextAttribute C424 POP BC Restore the attribute counter from the stack.
C425 DEC BC Decrease the attribute counter by one.
C426 INC DE Move on to the next attribute.
C427 LD A,B Jump back to DrawPicture_AttributesLoop until the attribute counter is zero.
C428 OR C
C429 JR NZ,DrawPicture_AttributesLoop
C42B LD (IY+$01),$FF Write FF to *DrawPicture_Third and *DrawPicture_Thirds. BASIC never POKEs these bytes, so the next picture again takes its screen third and number of thirds from its own record.
C42F LD (IY+$02),$FF
C433 RET Return.
Write the next byte of picture data to *DE. While a run of repeated bytes is being written, bit 2 of *DrawPicture_Flags is set, B' holds the count and C' holds the value.
DrawPicture_FetchByte C434 BIT 2,(IY+$03) Jump to DrawPicture_ReadByte if no run is in progress.
C438 JR Z,DrawPicture_ReadByte
C43A EXX Switch to the shadow registers.
C43B DEC B Decrease the run count in B' by one.
C43C LD A,C A=the run value from C'.
C43D EXX Switch back to the normal registers.
C43E JR Z,DrawPicture_EndRun Jump to DrawPicture_EndRun if the run has finished.
C440 LD (DE),A Write the run value to *DE.
C441 JR DrawPicture_Continue Jump to DrawPicture_Continue.
DrawPicture_EndRun C443 RES 2,(IY+$03) Clear bit 2 of *DrawPicture_Flags, as the run has finished.
DrawPicture_ReadByte C447 LD A,(HL) A=the next byte of picture data, and move HL on.
C448 INC HL
C449 AND A Jump to DrawPicture_WriteByte if it is not zero, to write it as it is.
C44A JR NZ,DrawPicture_WriteByte
C44C LD A,(HL) A zero byte starts a run. B'=the count.
C44D EXX
C44E LD B,A
C44F EXX
C450 INC HL Move HL on to the value.
C451 LD A,(HL) C'=the value (A holds it too).
C452 EXX
C453 LD C,A
C454 EXX
C455 INC HL Move HL on to the next byte of picture data.
C456 SET 2,(IY+$03) Set bit 2 of *DrawPicture_Flags, as a run is in progress.
DrawPicture_WriteByte C45A LD (DE),A Write the byte to *DE.
DrawPicture_Continue C45B BIT 3,(IY+$03) Jump back to DrawPicture_NextAttribute if the attributes are being drawn.
C45F JR NZ,DrawPicture_NextAttribute
C461 JR DrawPicture_NextByte Else jump back to DrawPicture_NextByte.
View the equivalent code in;
Prev: C352 Up: Map Next: C463