[{"data":1,"prerenderedAt":304},["ShallowReactive",2],{"learn:invaders:02-base":3},{"item":4,"marksAgainst":303},{"slug":5,"number":6,"title":7,"idea":8,"models":9,"body":12,"tryIt":241,"game":292,"cites":293,"program":302},"02-base",2,"Draw the base on the bottom row","a routine with CALL and RET, and the base's column in a byte of memory",[10,11],3,1,[13,19,23,27,78,85,88,110,113,130,133,140,142,150,161,164,172,174,197,201,203,231,234],{"kind":14,"inlines":15},"p",[16],{"kind":17,"text":18},"text","The player's base appears on the bottom row, three cells wide, in the middle of the screen. It does not move yet: this chapter draws it once, before the game loop starts, with a routine that the next chapters will call every time the base moves.",{"kind":20,"id":21,"text":22},"h2","what-changed","What changed",{"kind":14,"inlines":24},[25],{"kind":17,"text":26},"Chapter 1's program, with these changes:",{"kind":28,"items":29},"ul",[30,36,50,66],[31,34],{"kind":32,"text":33},"strong","~",{"kind":17,"text":35}," The comment at the top, lines 1 to 5, now describes chapter 2.",[37,39,41,44,46,48],{"kind":32,"text":38},"+",{"kind":17,"text":40}," ",{"kind":42,"text":43},"code","DRAWBASE",{"kind":17,"text":45},", a new routine with its comment, below ",{"kind":42,"text":47},"WAIT",{"kind":17,"text":49},": it copies three bytes to the base's place on row 15.",[51,52,54,56,58,60,62,64],{"kind":32,"text":38},{"kind":17,"text":53}," Two lines at the end of the clear, before ",{"kind":42,"text":55},"LOOP",{"kind":17,"text":57},": ",{"kind":42,"text":59},"LD HL,BASE",{"kind":17,"text":61}," and ",{"kind":42,"text":63},"CALL DRAWBASE",{"kind":17,"text":65},", which draw the base once.",[67,68,70,72,74,76],{"kind":32,"text":38},{"kind":17,"text":69}," The game's data, below the loop: ",{"kind":42,"text":71},"BASE",{"kind":17,"text":73},", the base's three cells, and ",{"kind":42,"text":75},"BASEX",{"kind":17,"text":77},", its column, with a comment.",{"kind":14,"inlines":79},[80,82,83],{"kind":17,"text":81},"Nothing is taken out, and ",{"kind":42,"text":47},{"kind":17,"text":84},", the clear and the loop are as they were.",{"kind":20,"id":86,"text":87},"the-base","The base",{"kind":14,"inlines":89},[90,92,94,96,98,100,102,104,106,107,108],{"kind":17,"text":91},"The screen is memory, 16 rows of 64 cells from ",{"kind":42,"text":93},"3C00H",{"kind":17,"text":95},", one byte a cell, so the bottom row, row 15, starts 15 times 64 cells in, at ",{"kind":42,"text":97},"3FC0H",{"kind":17,"text":99},". The base is three cells there, ",{"kind":42,"text":101},"0BCH",{"kind":17,"text":103},", ",{"kind":42,"text":105},"0BFH",{"kind":17,"text":103},{"kind":42,"text":101},{"kind":17,"text":109},":",{"kind":42,"lang":111,"text":112},"z80","BASE:   DB      0BCH,0BFH,0BCH  ; the base: a wing, a block, a wing",{"kind":14,"inlines":114},[115,117,119,121,122,124,125,127,128],{"kind":17,"text":116},"Bytes ",{"kind":42,"text":118},"80H",{"kind":17,"text":120}," to ",{"kind":42,"text":105},{"kind":17,"text":123}," are graphics: each cell is two blocks across and three down, and the low six bits light them, bit 0 top left, 1 top right, 2 and 3 the middle, 4 and 5 the bottom (as Fugløy's screen draws them, from the TRS-80's character generator). ",{"kind":42,"text":105},{"kind":17,"text":126}," lights all six; ",{"kind":42,"text":101},{"kind":17,"text":129},", bits 2 to 5, lights the lower two thirds, a wing. If you did lesson 5, this is its ship.",{"kind":20,"id":131,"text":132},"its-place-in-memory","Its place in memory",{"kind":14,"inlines":134},[135,137,139],{"kind":17,"text":136},"The game has to know where the base is, so that later chapters can move it, fire from it and see what hits it. That is one byte of memory, given a name and a first value by ",{"kind":42,"text":138},"DB",{"kind":17,"text":109},{"kind":42,"lang":111,"text":141},"BASEX:  DB      30              ; the base's column, 0 to 61",{"kind":14,"inlines":143},[144,146,148],{"kind":17,"text":145},"Column 30 of 64 puts the base in the middle. It can go no further right than 61, since it is three cells wide and the row ends at column 63. ",{"kind":42,"text":147},"LD A,(BASEX)",{"kind":17,"text":149}," reads the byte into A; of the 8-bit registers, only A can be loaded from a named address like that.",{"kind":14,"inlines":151},[152,153,154,155,157,159],{"kind":42,"text":71},{"kind":17,"text":61},{"kind":42,"text":75},{"kind":17,"text":156}," sit below the game loop. The processor runs a program's bytes in order, so data must be where it never arrives: the loop's ",{"kind":42,"text":158},"JR LOOP",{"kind":17,"text":160}," jumps back every time, and nothing after it is ever run as code.",{"kind":20,"id":162,"text":163},"drawbase-a-routine","DRAWBASE, a routine",{"kind":14,"inlines":165},[166,167,169,170],{"kind":42,"text":43},{"kind":17,"text":168}," works out the base's left cell from ",{"kind":42,"text":75},{"kind":17,"text":171},", and copies the three bytes HL points at there:",{"kind":42,"lang":111,"text":173},"DRAWBASE:\n        PUSH    BC              ; save BC, which LDIR counts down\n        LD      A,(BASEX)       ; the base's column ...\n        ADD     A,0C0H          ; ... plus 3FC0H, row 15: the base's left cell\n        LD      E,A\n        LD      D,3FH\n        LD      BC,3            ; three bytes\n        LDIR                    ; from (HL) to (DE), one byte at a time\n        POP     BC              ; BC as the caller left it\n        RET",{"kind":14,"inlines":175},[176,178,179,181,183,185,187,189,191,193,195],{"kind":17,"text":177},"The address is ",{"kind":42,"text":97},{"kind":17,"text":180}," plus the column. The column is at most 61, and ",{"kind":42,"text":182},"0C0H",{"kind":17,"text":184}," plus 61 is ",{"kind":42,"text":186},"0FDH",{"kind":17,"text":188},", still one byte, so the high byte is always ",{"kind":42,"text":190},"3FH",{"kind":17,"text":192}," and only the low byte needs the sum. ",{"kind":42,"text":194},"LDIR",{"kind":17,"text":196}," copies the byte at HL to the address in DE, adds 1 to HL and to DE, takes 1 from BC, and repeats until BC is 0: three bytes here.",{"kind":14,"inlines":198},[199],{"kind":17,"text":200},"The program draws the base once, after the clear:",{"kind":42,"lang":111,"text":202},"        LD      HL,BASE         ; draw the base where BASEX says\n        CALL    DRAWBASE",{"kind":14,"inlines":204},[205,206,208,209,211,213,215,216,218,219,221,223,224,226,228,229],{"kind":42,"text":63},{"kind":17,"text":207}," pushes the address of the next instruction onto the stack, taking SP down by 2, and jumps to ",{"kind":42,"text":43},{"kind":17,"text":210},"; its ",{"kind":42,"text":212},"RET",{"kind":17,"text":214}," pops that address back, SP up by 2, and the program goes on from there, into the loop. HL says what to draw, so the same routine can draw anything three cells wide where the base is: in the next chapter it also draws three spaces, to erase it. As ",{"kind":42,"text":47},{"kind":17,"text":217}," does, ",{"kind":42,"text":43},{"kind":17,"text":220}," keeps BC on the stack with ",{"kind":42,"text":222},"PUSH",{"kind":17,"text":61},{"kind":42,"text":225},"POP",{"kind":17,"text":227},", since ",{"kind":42,"text":194},{"kind":17,"text":230}," counts it down to 0.",{"kind":20,"id":232,"text":233},"on-the-model-i","On the Model I",{"kind":14,"inlines":235},[236,238,239],{"kind":17,"text":237},"The Model I's screen is the same memory at ",{"kind":42,"text":93},{"kind":17,"text":240},", so the program runs on it unchanged.",[242,276],{"kind":14,"inlines":243},[244,246,247,249,251,252,254,256,258,260,262,264,266,268,270,272,274],{"kind":17,"text":245},"Change ",{"kind":42,"text":75},{"kind":17,"text":248},"'s ",{"kind":42,"text":250},"DB 30",{"kind":17,"text":120},{"kind":42,"text":253},"DB 0",{"kind":17,"text":255}," and press Run ▶: the base sits at the left edge. Try ",{"kind":42,"text":257},"DB 61",{"kind":17,"text":259}," for the right edge. With ",{"kind":42,"text":261},"DB 62",{"kind":17,"text":263}," only two cells show: the base's left cell is ",{"kind":42,"text":265},"3FFEH",{"kind":17,"text":267},", so its right wing goes to ",{"kind":42,"text":269},"4000H",{"kind":17,"text":271},", one past the screen's last byte, ",{"kind":42,"text":273},"3FFFH",{"kind":17,"text":275},", into ordinary memory, where nothing draws it.",{"kind":14,"inlines":277},[278,280,281,283,284,285,287,289,290],{"kind":17,"text":279},"Then change the ",{"kind":42,"text":105},{"kind":17,"text":282}," in the middle of ",{"kind":42,"text":71},{"kind":17,"text":120},{"kind":42,"text":286},"0B3H",{"kind":17,"text":288}," and run it again. ",{"kind":42,"text":286},{"kind":17,"text":291}," lights bits 0, 1, 4 and 5: the top and bottom blocks of the middle cell, with a gap between them.",null,[294,298],{"source":295,"page":296,"about":297},"m3-trm","14","the Model III's screen is video memory at 3C00H, 1,024 bytes",{"source":299,"page":300,"about":301},"m1-trh","12","the Model I's screen is video memory at 3C00H, 16 lines of 64 characters","; Build Space Invaders, chapter 2: the base on the bottom row. Chapter 1's\n; blank screen and game loop, and before the loop starts, the player's base\n; is drawn on row 15: three cells, copied to the screen by a routine,\n; DRAWBASE, at the column a byte of memory, BASEX, holds. The loop still\n; only waits; the next chapter moves the base.\n\n        ORG     7000H           ; the program lives at 7000H, in free memory\n\n; WAIT: a counted delay, 5,120 passes of 26 T-states, about 66 ms a turn at\n; 2.03 MHz. The routines come first, and the game itself after them, from\n; START, where END START says the program begins.\nWAIT:   PUSH    BC              ; save BC, which the loop uses\n        LD      BC,1400H        ; 1400H is 5,120 passes of 26 T-states\nDELAY:  DEC     BC\n        LD      A,B\n        OR      C\n        JR      NZ,DELAY\n        POP     BC              ; BC as the caller left it\n        RET\n\n; DRAWBASE: copy the three bytes HL points at to the base's place on row 15,\n; 3FC0H plus BASEX. BC is kept on the stack; A, DE and HL are not.\nDRAWBASE:\n        PUSH    BC              ; save BC, which LDIR counts down\n        LD      A,(BASEX)       ; the base's column ...\n        ADD     A,0C0H          ; ... plus 3FC0H, row 15: the base's left cell\n        LD      E,A\n        LD      D,3FH\n        LD      BC,3            ; three bytes\n        LDIR                    ; from (HL) to (DE), one byte at a time\n        POP     BC              ; BC as the caller left it\n        RET\n\nSTART:  LD      HL,3C00H        ; HL points at the top-left cell\n        LD      BC,400H         ; BC counts the cells: 400H is 1024\nCLEAR:  LD      (HL),20H        ; a space: the cell is blank\n        INC     HL              ; on to the next cell\n        DEC     BC              ; one cell fewer to go (DEC BC sets no flags ...)\n        LD      A,B             ; ... so test BC by hand: copy B into A\n        OR      C               ; and OR in C: zero only when B and C both are\n        JR      NZ,CLEAR        ; not zero yet: clear the next cell\n        LD      HL,BASE         ; draw the base where BASEX says\n        CALL    DRAWBASE\n\n; The game loop: one turn of the game, then round again. A game's turn\n; reads the keys, moves things and draws them; this one only waits.\nLOOP:   CALL    WAIT            ; the turn's pause, so the game runs at a steady speed\n        JR      LOOP            ; and round again, for ever\n\n; The game's data: below the loop, where the processor never runs into it.\nBASE:   DB      0BCH,0BFH,0BCH  ; the base: a wing, a block, a wing\nBASEX:  DB      30              ; the base's column, 0 to 61\n\n        END     START           ; the program starts at START\n","; Build Space Invaders, chapter 1: a blank screen and a game loop that does\n; nothing yet. The program clears the screen, all 1,024 cells of video memory\n; at 3C00H-3FFFH, to spaces, then goes round its game loop for ever: each turn\n; waits a counted 66 ms and goes round again. The chapters that follow give\n; the loop its work, one piece at a time, until it is a game.\n\n        ORG     7000H           ; the program lives at 7000H, in free memory\n\n; WAIT: a counted delay, 5,120 passes of 26 T-states, about 66 ms a turn at\n; 2.03 MHz. The routines come first, and the game itself after them, from\n; START, where END START says the program begins.\nWAIT:   PUSH    BC              ; save BC, which the loop uses\n        LD      BC,1400H        ; 1400H is 5,120 passes of 26 T-states\nDELAY:  DEC     BC\n        LD      A,B\n        OR      C\n        JR      NZ,DELAY\n        POP     BC              ; BC as the caller left it\n        RET\n\nSTART:  LD      HL,3C00H        ; HL points at the top-left cell\n        LD      BC,400H         ; BC counts the cells: 400H is 1024\nCLEAR:  LD      (HL),20H        ; a space: the cell is blank\n        INC     HL              ; on to the next cell\n        DEC     BC              ; one cell fewer to go (DEC BC sets no flags ...)\n        LD      A,B             ; ... so test BC by hand: copy B into A\n        OR      C               ; and OR in C: zero only when B and C both are\n        JR      NZ,CLEAR        ; not zero yet: clear the next cell\n\n; The game loop: one turn of the game, then round again. A game's turn\n; reads the keys, moves things and draws them; this one only waits.\nLOOP:   CALL    WAIT            ; the turn's pause, so the game runs at a steady speed\n        JR      LOOP            ; and round again, for ever\n\n        END     START           ; the program starts at START\n",1792464470931]